I'm making a multiplot in matplotlib that displays a molecule structure made with RDKit in one of the axes/subplots. I know you can display raster images with imshow
, but what I want is just being able to load an SVG as an SVG into one of my subplots.
I have taken the code from this answer to obtain the raw plain text of the SVG of the molecule. I could save it and convert it with cairoSVG to a raster image that can be then loaded with imshow, but I feel like there must be a way to just display an image (or in this case, text string) that is already an SVG in a mpl subplot. Is that possible or am I forced to take a detour through PNG pixelisation?
Note: The cairo code doesn't even work for me bc I get the OSError that it isn't properly installed, but if I didn't have that problem my code should work just fine. For the time being I left it commented out and replaced it with a random numpy array for style points.
import numpy as np
import matplotlib.pyplot as plt
# from cairosvg import svg2png
from rdkit import Chem
from rdkit.Chem import rdDepictor
from rdkit.Chem.Draw import rdMolDraw2D
smiles = 'C1=CC(=C(C=C1C2=C(C(=O)C3=C(C=C(C=C3O2)O)O)O)O)O'
def moltosvg(mol, molSize = (300,300), kekulize = True):
mc = Chem.Mol(mol.ToBinary())
if kekulize:
try:
Chem.Kekulize(mc)
except:
mc = Chem.Mol(mol.ToBinary())
if not mc.GetNumConformers():
rdDepictor.Compute2DCoords(mc)
drawer = rdMolDraw2D.MolDraw2DSVG(molSize[0],molSize[1])
drawer.DrawMolecule(mc)
drawer.FinishDrawing()
svg = drawer.GetDrawingText()
return svg.replace('svg:','')
def plot(text,smiles):
m = Chem.MolFromSmiles(smiles)
svg_string = moltosvg(m)
# svg2png(bytestring=svg_code,write_to='output.png')
lorem_ipsum = [np.random.uniform(0,1,100) for i in range(100)]
fig = plt.figure(frameon=False, figsize=(6,3))
gs = fig.add_gridspec(ncols=2, hspace=0, wspace=0, width_ratios=[1,1])
axes = gs.subplots()
for ax in axes:
for spine in ax.spines.values():
spine.set_visible(False)
ax.tick_params(bottom=False, labelbottom=False, left=False, labelleft=False)
axes[0].text(1.,0.5,text,size=20,ha='right',va='center',transform=axes[0].transAxes)
axes[1].imshow(lorem_ipsum)
plt.show()
plot('TEST',smiles)