1111from pandas .core .groupby import DataFrameGroupBy
1212from plotly .graph_objects import Figure
1313from rdkit import Chem
14+ from rdkit .Chem .rdchem import Mol
1415from rdkit .Chem .Draw import rdMolDraw2D
1516
1617
@@ -87,6 +88,7 @@ def add_molecules(
8788 fig : Figure ,
8889 df : pd .DataFrame ,
8990 smiles_col : str | list [str ] = "SMILES" ,
91+ mol_col : Mol | list [Mol ] = None ,
9092 show_img : bool = True ,
9193 svg_size : int = 200 ,
9294 alpha : float = 0.75 ,
@@ -173,10 +175,23 @@ def add_molecules(
173175 colors = {0 : "black" }
174176
175177 app = JupyterDash (__name__ )
178+ if smiles_col is None and mol_col is None :
179+ raise ValueError ("Either smiles_col or mol_col has to be specified!" )
180+
176181 if isinstance (smiles_col , str ):
177182 smiles_col = [smiles_col ]
183+ if isinstance (mol_col , str ):
184+ mol_col = [mol_col ]
178185
179- if len (smiles_col ) > 1 :
186+ if mol_col is not None and len (mol_col ) > 1 :
187+ menu = dcc .Dropdown (
188+ options = [{"label" : x , "value" : x } for x in mol_col ],
189+ value = mol_col [0 ],
190+ multi = True ,
191+ id = "smiles-menu" ,
192+ placeholder = "Select a mol column to display" ,
193+ )
194+ elif smiles_col is not None and len (smiles_col ) > 1 :
180195 menu = dcc .Dropdown (
181196 options = [{"label" : x , "value" : x } for x in smiles_col ],
182197 value = smiles_col [0 ],
@@ -209,7 +224,10 @@ def display_hover(hoverData, value):
209224 return False , no_update , no_update
210225
211226 if value is None :
212- value = smiles_col
227+ if mol_col is not None :
228+ value = mol_col
229+ elif smiles_col is not None :
230+ value = smiles_col
213231 if isinstance (value , str ):
214232 chosen_smiles = [value ]
215233 else :
@@ -229,21 +247,33 @@ def display_hover(hoverData, value):
229247 hoverbox_elements = []
230248
231249 if show_img :
232- # The 2D image of the molecule is generated here
233250 for col in chosen_smiles :
234251 smiles = df_row [col ]
235252 buffered = BytesIO ()
236- d2d = rdMolDraw2D .MolDraw2DSVG (svg_size , svg_size )
237- opts = d2d .drawOptions ()
238- opts .clearBackground = False
239- d2d .DrawMolecule (Chem .MolFromSmiles (smiles ))
240- d2d .FinishDrawing ()
241- img_str = d2d .GetDrawingText ()
242- buffered .write (str .encode (img_str ))
243- img_str = base64 .b64encode (buffered .getvalue ())
244- img_str = f"data:image/svg+xml;base64,{ repr (img_str )[2 :- 1 ]} "
245- # img_str = df_data.query(f"{col} == @smiles")[f"{col}_img"].values[0]
253+ if isinstance (smiles , str ):
254+ # Generate 2D SVG if smiles column is a string
255+
256+ d2d = rdMolDraw2D .MolDraw2DSVG (svg_size , svg_size )
257+ opts = d2d .drawOptions ()
258+ opts .clearBackground = False
259+ d2d .DrawMolecule (Chem .MolFromSmiles (smiles ))
260+ d2d .FinishDrawing ()
261+ img_str = d2d .GetDrawingText ()
262+ buffered .write (str .encode (img_str ))
263+ img_str = base64 .b64encode (buffered .getvalue ())
264+ img_str = f"data:image/svg+xml;base64,{ repr (img_str )[2 :- 1 ]} "
265+
266+ elif isinstance (smiles , Mol ):
267+ # if smiles column is a Mol object, use the 3D coordinates of the mol object
268+ img = Chem .Draw .MolToImage (smiles )
269+ img .save (buffered , format = "PNG" )
270+ img_str = base64 .b64encode (buffered .getvalue ())
271+ img_str = "data:image/png;base64,{}" .format (repr (img_str )[2 :- 1 ])
246272
273+ else :
274+ raise TypeError (
275+ "smiles_col or mol_col not specified with the correct type."
276+ )
247277 if len (smiles_col ) > 1 :
248278 hoverbox_elements .append (
249279 html .H2 (
0 commit comments