Drawing ======= Note that this tutorial requires the scipy and matplotlib packages to be installed. See installation instructions. It is very easy to check the correctness of a CGsmiles string by simply drawing the molecule and the mapping to the coarser level. Drawing molecules can be accomplished using the drawing module. The drawing function takes any networkx graph, assumes it is a molecule and makes a 2D drawing using an `vespr` layout. The following example demonstrates how to draw the mapping for Martini 3 Benzene. .. code:: python import cgsmiles from cgsmiles.drawing import draw_molecule import matplotlib.pyplot as plt # Martini 3 Benzene cgsmiles_str = "{[#TC5]1[#TC5][#TC5]1}.{#TC5=[$]cc[$]}" # Resolve molecule into networkx graphs res_graph, mol_graph = cgsmiles.MoleculeResolver.from_string(cgsmiles_str).resolve() # Draw molecule at different resolutions fig, ax = plt.subplots(1, 1) draw_molecule(mol_graph, ax=ax) # Display the drawing plt.show() By setting ``cg_mapping=False`` only the atomic resolution molecule is drawn. Sometimes it is handy to not draw all the hydrogen atoms of a molecule. To do so one can use pysmiles to remove hydrogen atoms and then simply provide node labels that will show the atom plus the hydrogen count. The example below illustrates this for poly(ethylene) glycol. .. code:: python import pysmiles import networkx as nx import cgsmiles from cgsmiles.drawing import draw_molecule import matplotlib.pyplot as plt # PEO Polymer cgsmiles_str = "{[#PEO]|10}.{#PEO=[$]COC[$]}" # Resolve molecule into networkx graphs res_graph, mol_graph = cgsmiles.MoleculeResolver.from_string(cgsmiles_str).resolve() # Remove hydrogen atoms # Each carbon atom gets a node keyword `hcount` pysmiles.remove_explicit_hydrogens(mol_graph) # Now we generate the node labels labels = {} for node in mol_graph.nodes: hcount = mol_graph.nodes[node].get('hcount', 0) label = mol_graph.nodes[node].get('element', '*') if hcount > 0: label = label + f"H{hcount}" labels[node] = label # Draw molecule at different resolutions fig, ax = plt.subplots(1, 1) draw_molecule(mol_graph, ax=ax, labels=labels, scale=1) ax.set_frame_on('True') # Display the drawing plt.show() Likely, you will see that not the entire molecule fits in the bounding box as indicated by the frame. The reason is that the drawing function does not automatically scale the image. You have two choices now. You can use the scale keyword to shrink the molecule image until it fits (e.g. ``scale=0.5``) or you can provide a larger canvas. .. code:: python import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 1, figsize=(20, 6)) ... ax, pos = draw_molecule(mol_graph, labels=labels, scale=1, ax=ax) The advantage of not automatically fitting the drawing into the bounding box is that if you draw multiple molecules they will all have exactly the same size in terms of labels, bonds, and atoms. Thus you only have to find a visually pleasing canvas size once and can draw a large collection of molecules. One added bonus feature of the drawing utility is that it will draw cis/trans isomers correctly according to the cgsmiles string the user has provided. You can see a simple example below. .. code:: python import cgsmiles from cgsmiles.drawing import draw_molecule import matplotlib.pyplot as plt # let's have two panels for each molecule fig, axes = plt.subplots(1,2, figsize=(6, 6)) # trans butene cgsmiles_str_tans = "{[#A][#B]}.{#A=C\C=[$],#B=[$]=C\C}" # cis butene cgsmiles_str_cis = "{[#A][#B]}.{#A=C\C=[$],#B=[$]=C/C}" # Resolve molecule into networkx graphs for ax, cgstr in zip(axes, [cgsmiles_str_tans, cgsmiles_str_cis]): res_graph, mol_graph = cgsmiles.MoleculeResolver.from_string(cgstr).resolve() pysmiles.remove_explicit_hydrogens(mol_graph) # Now we generate the node labels labels = {} for node in mol_graph.nodes: hcount = mol_graph.nodes[node].get('hcount', 0) label = mol_graph.nodes[node].get('element', '*') if hcount > 0: label = label + f"H{hcount}" labels[node] = label # Draw molecule at different resolutions ax, pos = draw_molecule(mol_graph, ax=ax, labels=labels) # Display the drawing plt.show()