Building an irregular Dendrimer#
We already built a Polyphenylene dendrimer in another tutorial. In that case we only needed one single fragment, a benzene ring, to create the entire structure. In this tutorial we will make a dendrimer that consist of multiple different fragments.
Specifically, we will tackle this structure here:

“Synthesis of Open-Resorcinarene Dendrimers with L-serine (Ibuprofen) Derivatives”. Pedro-Hernández, Daniel Luis, Martínez-García , Marcos,Current Organic Chemistry, volume 26, issue 1, pages 71-80, year 2022, issn 1385-2728/1875-5348, doi 10.2174/1385272825666211130164548
The authors that described the synthesis kindly already provided some good hints as to the fragments we could use to assemble our model. Let’s adhere to their color coding and assemble the structure from inside to outside, using the fragments that are highlighted in color.
[10]:
import buildamol as bam
Let’s begin by making the orange core
[11]:
# let's get a benzene to use for the core
bnz = bam.Molecule.from_smiles("C1=CC=CC=C1", id="BNZ")
# make the central dimethylbenzene
core = bam.methylate(bnz.copy(), ["C1", "C4"])
# now make the chlorobenzenes
cbz = bnz.copy()
cbz.rename_residue(1, "CBZ")
cbz.change_element("H3", "Cl")
# now connect the chlorobenzenes to the methyl groups
link = bam.linkage("C", "C1")
for residue in core.get_residues("CH3"):
for i in range(2):
core.attach(cbz, link, at_residue=residue)
core.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
[12]:
# now let's optimize the core
core.optimize()
core.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
[13]:
# now add the amide part of the core
amd = bam.Molecule.from_smiles("NC(CO)=O", id="AMD").autolabel()
# let's copy to be on the save side...
_core = core.copy()
link = bam.linkage(None, "O2")
for residue in core.get_residues("CBZ"):
for atom1 in ("C4", "C6"):
link.atom1 = atom1
_core.attach(amd, link, at_residue=residue)
_core.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
Now that we have the core ready, we can make the branches. We will use fragments just like the ones that were highlighted in the original figure.
[15]:
# the green molecule
prp = bam.Molecule.from_smiles("CC(C)CC1=CC=C(C(C=O)C)C=C1", id="PRP")
prp.autolabel()
prp.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
[16]:
# the blue molecule
trz = bam.Molecule.from_smiles("NC(CO)C(OCC1=C[N+](CC)=NN1)=O", id="TRZ")
trz.autolabel()
trz.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
[17]:
# the red molecule
trm = bam.Molecule.from_smiles("CC(OC(CO)=O)(C)C", id="TRM")
trm.autolabel()
trm.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
Now we can start to assemble the branches.
Because we added some functional groups to the fragments we can let them “react” without having to identify the particular atoms that will form bonds manually. Here’s how:
[18]:
# connect green and blue
ext1 = bam.react(prp, trz, bam.structural.groups.aldehyde, bam.structural.groups.amine)
# now add the red
ext1 = bam.react(ext1, trm, bam.structural.groups.hydroxyl, bam.structural.groups.hydroxyl)
ext1.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
Let’s also optimize this one…
[20]:
ext1.optimize()
ext1.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
And that’s it. Now we have our branches that we can connect to the core! Let’s do it:
[26]:
# let's define the linkage to add the branches to the core
link = bam.linkage("N1", "C8")
# again a copy to be save...
assembled = _core.copy()
# let's use operator syntax this time...
# set default linkage and attach residue of ext1
assembled % link
ext1 @ "TRZ"
# attach the branches to the core
for residue in assembled.get_residues("AMD"):
for i in range(2):
assembled = assembled @ residue + ext1
assembled.show()
/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:
When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.
Data type cannot be displayed: application/vnd.plotly.v1+json
And there we have our assembled dendrimer! It still looks like quite a few of the branches are colliding with each other, however. So let’s optimize the conformation!
Here’s our strategy for how to do it. Since we only need the branches to be optimized we will select only bonds in the branches for optimization. Here’s how we can do it:
[51]:
# we'll make a set of all bonds that connect residues from the branches
# using our branch template molecule
outer_edges = set()
for i in ext1.get_residues():
outer_edges.update(
assembled.get_residue_connections(i.resname)
)
# let's check out what bonds we have selected
v = assembled.draw(show_atoms=False)
v.draw_edges(*outer_edges, color="limegreen", linewidth=3, showlegend=False)
v.show()
Data type cannot be displayed: application/vnd.plotly.v1+json
Now that we have a set of bonds to optimize for, let’s make a graph and optimize the structure!
[ ]:
G = assembled.get_atom_graph()
outer_edges = G.direct_edges(assembled.get_atom(1), outer_edges)
[50]:
# since the structure is pretty large we will likely have to play around a bit with the hyperparameters here...
env = bam.DistanceRotatron(G, outer_edges, pushback=5, radius=10, clash_distance=2)
opt = bam.optimize(assembled.copy(), env)
opt.to_pdb("./files/assembled.pdb")
Alrighty, let’s look at what we have got:
[52]:
opt.show(show_atoms=False)
Data type cannot be displayed: application/vnd.plotly.v1+json
That looks quite descent, let’s take it!
And with that we have reached the end of this tutorial. Given how complex the dendrimer is, it did not take that much code to build it, just 43 lines of code (ignoring the mol.show() lines) - that’s quite moderate, don’t you think?
Thank’s for checking out this tutorial and good luck with your research using BuildAMol!