Break rotatable bonds and report the fragments

This task is meant to give examples of how to add and delete atoms and bonds from the molecular graph, using the graph API.

One of the researchers I worked with asked me for a program which took an input molecule and broke it apart at the rotatable bonds. When a bond breaks, each fragment gets attached to an atom with atomic number 0, that is "*".

For a simple example, "c1ccccc1C=O" would become "c1ccccc1*" and "*C=O".

"Rotatable bond" was defined as the bond in the following SMARTS

[!$([NH]!@C(=O))&!D1&!$(*#*)]-&!@[!$([NH]!@C(=O))&!D1&!$(*#*)]

but a toolkit may have a built-in definition of rotatable bond.

Implementation
Write a function or method which takes a molecule as input and finds all of the rotatable bonds using either the toolkit's built-in definition or the above SMARTS definition. Delete each bond from the structure and add an atom with atomic number 0 to each of the atoms which was at the end of the bond. The function may modify the molecule in-place or return a new molecule.

Use the function to write a program which takes the structure "c1ccc2c(c1)C(=NC(C(=O)N2CC(=O)O)Cc3ccc(cc3)O)c4cccc(c4)O" (which is the perceived aromatic form of PubChem CID 391758), breaks the rotatable bonds, and prints the fragments out in SMILES form, one per line.

The output should be something like


 * c1(ccc(cc1)O)*
 * c1(cccc(c1)O)*
 * [CH]1(C(=O)[N](c2ccccc2C(=N1)(*)*)(*)*)*
 * [CH2](*)(*)*
 * [CH2](*)(*)*
 * C(=O)(*)O

although the specific strings will depend on the toolkit's canonicalization algorithm.

If the toolkit can do this with SMIRKS then feel free to show how that works, in addition to a solution which manipulates the graph directly. (Frankly, I haven't figured out how to do it with SMIRKS in OEChem.)

Cactvs/Tcl
set eh [ens create "c1ccc2c(c1)C(=NC(C(=O)N2CC(=O)O)Cc3ccc(cc3)O)c4cccc(c4)O"] prop setparam E_SMILES useexplicith 1 filter create rotbonds property B_ROTATABILITY operator = value1 yes foreach b [ens bonds $eh rotbonds] { lassign [bond atoms $eh $b] a1 a2       bond delete $eh $b bond create $eh [list $a1 [atom add $eh *]] bond create $eh [list $a2 [atom add $eh *]] } foreach fragsmiles [ens get $eh M_SMILES] { puts $fragsmiles }

Output: C1(=C(C2=C(C(=C1[H])[H])N(C(C(N=C2*)([H])*)=O)*)[H])[H] C([H])([H])(*)* C(=O)(O[H])* C([H])([H])(*)* C3(=C(C(=C(C(=C3[H])[H])O[H])[H])[H])* C4(=C(C(=C(C(=C4[H])[H])[H])O[H])[H])*

And here is the requested version using SMIRKS with the provided rotatable bond definition pattern: set eh [ens create "c1ccc2c(c1)C(=NC(C(=O)N2CC(=O)O)Cc3ccc(cc3)O)c4cccc(c4)O"] prop setparam E_SMILES useexplicith 1 set transform {[!$([NH]!@C(=O))&!D1&!$(*#*):1]-&!@[!$([NH]!@C(=O))&!D1&!$(*#*):2]>>[*:1]*.[*:2]*} set eh [ens transform $eh [list $transform] forward exhaustive] foreach fragsmiles [ens get $eh M_SMILES] { puts $fragsmiles }

The output is the same. Using SMIRKS is slower than the first version, though, and it requires toolkit version 3.384 or later. Previous versions ignored non-standard atoms for degree computations, without the option to include query atoms, and since the D attribute is used in the SMIRKS transform, the outcome was not what is expected.

Cactvs/Python
The first solution scripted in Python looks like this:

e=Ens("c1ccc2c(c1)C(=NC(C(=O)N2CC(=O)O)Cc3ccc(cc3)O)c4cccc(c4)O") Prop.Setparam('E_SMILES','useexplicith',1) f=Filter('rotbonds','property','B_ROTATABILITY','operator','=','value1','yes') for b in e.bonds(f): (a1,a2)=b.atoms b.delete Bond(e,(a1,Atom(e,'*'))) Bond(e,(a2,Atom(e,'*'))) for fragsmiles in e.M_SMILES: print(fragsmiles)

The output is identical.