Is converting SMARTS to SMILES a "lossless" operation?

The following three different SMARTS strings represent the same structure - at least when depicting it (e.g. at [Uni Hamburg Smarts viewer](http://smartsview.zbh.uni-hamburg.de/smartsview/view)).



```
SMARTS:  
[#6]-1=[#6]-[#6](-[#6]-[#6](-[#6]-1)-[#6])=[#8]  
[#6]-1-[#6]=[#6]-[#6](-[#6]-[#6]-1-[#6])=[#8]  
[#6]-1-[#6](-[#6]=[#6]-[#6]-[#6]-1-[#6])=[#8]  

```

Also, the chemical structure represented in SMILES leads to only one string, at least only one I can think of.



```
SMILES:
CC1CC=CC(=O)C1

```

Now, I do know the differences between SMARTS and SMILES, and I do know what the symbols in SMARTS mean. Still, I tried several softwares to find any differences in the use between SMARTS and SMILES representation *for that specific case*, and couldn't find any.


So I wonder if I could use SMILES in that case, or if there's any danger of missing information, for example when searching for substructures?




[SMARTS](http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html) is deliberately designed to be a superset of SMILES. That is, any valid SMILES depiction should also be a valid SMARTS query, one that will retrieve the very structure that the SMILES string depicts.


However, as a query language, SMARTS can be more general than SMILES is. For example, `CC` as a SMILES string depicts a single compound: ethane. As a SMARTS query, though, `CC` will match ethane, but will also match propane, acetic acid, cyclohexane, vancomycin, etc.


There's also SMARTS strings which are not valid SMILES strings. You list several in your question: `[#6]-1=[#6]-[#6](-[#6]-[#6](-[#6]-1)-[#6])=[#8]` is not a valid SMILES representation, unless your SMILES parser is being particularly generous. Even if it is, `[#6]-1=[#6]-[#6](-[#6]-[#6](-[#6]-1)-[#6])=[#8,#7]` is also a valid SMARTS query which should match your molecule, but not even a generous SMILES parser is likely to accept it.


Despite being similar, SMARTS and SMILES are intended for fundamentally different things - the purpose of SMILES is to represent particular compounds, whereas SMARTS represents a query against a range of possible molecules, or an abstract description of a set of possible molecules. As such, they're not inter-convertible, even if the strings are literally identical.


For your *particular* case, yes, `CC1CC=CC(=O)C1` is both a valid SMILES and a valid SMARTS, but as a SMARTS query, it represents not just 5-methyl-2-cyclohexen-1-one, but also 5-propyl-2-cyclohexen-1-one and 3-hydroxy-5-butyl-6-amino-2-cyclohexen-1-one, as well as many others, all of which contain that substructure. The SMARTS viewer you link doesn't depict this explicitly, because it's implicit in the use of SMARTS that it's a substructure pattern for a broader class of compounds.


 9

Thilo asked a similar question on the `rdkit-discuss` mailing list, where Andrew Dalke chimed in with this response, which he gave me permission to post here. The answer uses the python-based rdkit library to give examples of converting between SMILES and SMARTS and other tasks.


From Andrew Dalke:


On Apr 19, 2017, at 12:03, Thilo Bauer wrote:



> 
> Is converting SMARTS to SMILES a "lossless" operation, or does one loose
>  information on doing so?
> 
> 
> 


It is obviously not lossless if you include terms that cannot be represented in SMILES.



```
>>> from rdkit import Chem
>>> Chem.MolToSmiles(Chem.MolFromSmarts("[C,N]"))
'C'

```

or which don't make sense as a molecule:



```
>>> Chem.MolToSmiles(Chem.MolFromSmarts("c"))
'c'
>>> Chem.MolFromSmiles("c")
[23:02:24] non-ring atom 0 marked aromatic

```

It also loses some information which could be represented in SMILES:



```
>>> Chem.MolToSmiles(Chem.MolFromSmarts("[NH4+]"))
'N'
>>> Chem.MolToSmiles(Chem.MolFromSmarts("C[N+]1(C)CCCCC1"))
'CN1(C)CCCCC1'
>>> Chem.MolToSmiles(Chem.MolFromSmarts("[12C]"), isomericSmiles=True)
'C'

```

Do be careful if you want to handle aromatic atoms and bonds:



```
>>> Chem.MolToSmiles(Chem.MolFromSmarts("[#6]:1:[#6]:[#6]:[#6]:[#6]:[#6]:1"))
'C1:C:C:C:C:C:1'
>>> Chem.MolToSmiles(Chem.MolFromSmarts("c=1-c=c-c=c-c=1"))
'c1=c-c=c-c=c-1'

```


> 
> Background:
>  I've got three different SMARTS strings representing the same structure
>  - at least when depicting it. Also all three strings result in the exact
>  same SMILES (see code and output below).
> 
> 
> 


It looks like you want SMARTS canonicalization.


In general this is hard, because SMARTS can include boolean expressions and recursive SMARTS.


If you limit yourself to patterns like `'[#6]-1=[#6]-[#6]...'`, with only atomic numbers and single/double/triple bonds, then I think RDKit will do what you want.


[[CF: Andrew Dalke also had important answer-level commentary on R.M.'s answer, which I copy below.]]



> 
> From chemistry stack exchange, an answer contributed by user R.M.:
> 
> 
> SMARTS is deliberately designed to be a superset of SMILES. That is, any valid SMILES depiction should also be a valid SMARTS query, one that will retrieve the very structure that the SMILES string depicts.
> 
> 
> 


Except, that last clause isn't true. Try matching tritium against itself.



```
>>> from rdkit import Chem
>>> mol = Chem.MolFromSmiles("[3H]")
>>> pat = Chem.MolFromSmarts("[3H]")
>>> mol.HasSubstructMatch(pat)
False

```

For hydrogens you must use '#1', because H in SMARTS means something different.



```
>>> pat2 = Chem.MolFromSmarts("[3#1]")
>>> mol.HasSubstructMatch(pat2)
True

```

SMILES input under Daylight and most other toolkits gets normalized to the chemistry model, including aromaticity perception:



```
>>> mol = Chem.MolFromSmiles("C1=CC=CC=C1")
>>> pat = Chem.MolFromSmarts("C1=CC=CC=C1")
>>> mol.HasSubstructMatch(pat)
False
>>> pat2 = Chem.MolFromSmarts("c1ccccc1")
>>> mol.HasSubstructMatch(pat2)
True

```

RDKit also does a small amount of additional normalization, or 'sanitization' to use the RDKit term. For example, it will convert "neutral 5 coordinate Ns with double bonds to Os to the zwitterionic form" (see GraphMol/MolOps.cpp):



```
>>> s = "CN(=O)=O"
>>> mol = Chem.MolFromSmiles(s)
>>> pat = Chem.MolFromSmarts(s)
>>> mol.HasSubstructMatch(pat)
False
>>> Chem.MolToSmiles(mol)
'C[N+](=O)[O-]'

```

I believe that the output SMILES from a toolkit, assuming that the SMILES doesn't have an explicit hydrogen, can be used a SMARTS which will match the molecule made from that same SMILES, by that same toolkit.


 4

In this case, the SMARTS and SMILES represent the same (sub)-structure, in particular because the SMARTS pattern explicitly defines the single atom type and connectivity for all atoms. So to answer your question, yes, this case is a lossless conversion. 


In contrast, if the `O` could be an `O` or an `N`, the SMARTS would not catch that. And this both your SMILES and SMARTS would miss `N=C1C=CCC(C)C1`. However, you can write a SMARTS to match both `N=C1C=CCC(C)C1` and `O=C1C=CCC(C)C1`, but a SMILES will not.


Also, note that the SMILES could be written in many (equivalent) ways, e.g., `O=C1C=CCC(C)C1`


 1