def MolToJSON(mol, size=(300,300), kekulize=True, wedgeBonds=True, fitImage=False, options=None, **kwargs): if not mol: raise ValueError,'Null molecule provided' canvas = Canvas(size=size) if options is None: options = DrawingOptions() if fitImage: options.dotsPerAngstrom = int(min(size) / 10) options.wedgeDashedBonds = wedgeBonds try: drawer = MolDrawing(canvas=canvas,drawingOptions=options) except TypeError: drawer = MolDrawing(canvas=canvas) if kekulize: mol = Chem.Mol(mol.ToBinary()) Chem.Kekulize(mol) if not mol.GetNumConformers(): Compute2DCoords(mol) drawer.AddMol(mol,**kwargs) try: drawer.AddLegend(kwargs.get('legend', '')) except AttributeError: pass canvas.flush() return canvas.json #------------------------------------------------------------------------------
def _parseMolData(data): """Imports a molfile and verifies if all of the coordinates are set to zeros. if they are set to zeros then we know there are no real coordinates in the molfile In this case we allow RDKit to recaculate the positions of the atoms and come up with its own pictorial representation of the molecule If not we use the molecule as drawn""" suppl = SDMolSupplier() suppl.SetData(str(data), sanitize=False) data = [x for x in suppl if x] for x in data: if not x.HasProp("_drawingBondsWedged"): SanitizeMol(x) ctab = MolToMolBlock(x) ctablines = [ item.split("0.0000") for item in ctab.split("\n") if "0.0000" in item ] needs_redraw = 0 for line in ctablines: if len(line) > 3: needs_redraw += 1 if needs_redraw == len(ctablines): #check for overlapping molecules in the CTAB SanitizeMol(x) Compute2DCoords(x) return data
def annotate_chemical_svg(network): """Annotate chemical nodes with SVGs depiction. :param network: dict, network of elements as outputted by the sbml_to_json method :return: dict, network annotated """ from rdkit.Chem import MolFromInchi from rdkit.Chem.Draw import rdMolDraw2D from rdkit.Chem.AllChem import Compute2DCoords from urllib import parse for node in network['elements']['nodes']: if node['data']['type'] == 'chemical' and node['data'][ 'inchi'] is not None: inchi = node['data']['inchi'] try: mol = MolFromInchi(inchi) # if mol is None: # raise BaseException('Mol is None') Compute2DCoords(mol) drawer = rdMolDraw2D.MolDraw2DSVG(200, 200) drawer.DrawMolecule(mol) drawer.FinishDrawing() svg_draft = drawer.GetDrawingText().replace("svg:", "") svg = 'data:image/svg+xml;charset=utf-8,' + parse.quote( svg_draft) node['data']['svg'] = svg except BaseException as e: msg = 'SVG depiction failed from inchi: "{}"'.format(inchi) logging.warning(msg) logging.warning("Below the RDKit backtrace...") logging.warning(e) node['data']['svg'] = None return network
def update_mol_image(self, mol_name, save=False, verbosity=0): """ Generate mol images, if needed :param str mol_name: name of the molecule to be updated :param bool save: automatically save data :param int verbosity: controls verbosity level """ import rdkit.Chem from rdkit.Chem.Draw import MolDraw2DSVG from rdkit.Chem.AllChem import Compute2DCoords this_mol = self.ligands_data[mol_name]['molecule'] self.ligands_data[mol_name].setdefault('images', {}) if not {'2d_hs', '2d_nohs'}.issubset( self.ligands_data[mol_name]['images']): draw_2d_svg = MolDraw2DSVG(300, 300) temp_mol = rdkit.Chem.Mol(this_mol) Compute2DCoords(temp_mol) draw_2d_svg.drawOptions().addStereoAnnotation = True draw_2d_svg.DrawMolecule(temp_mol) draw_2d_svg.FinishDrawing() svg_data_hs = draw_2d_svg.GetDrawingText() temp_mol = rdkit.Chem.RemoveHs(temp_mol) Compute2DCoords(temp_mol) draw_2d_svg = MolDraw2DSVG(300, 300) draw_2d_svg.DrawMolecule(temp_mol) draw_2d_svg.FinishDrawing() svg_data_no_hs = draw_2d_svg.GetDrawingText() self.ligands_data[mol_name]['images'].update({ '2d_hs': svg_data_hs, '2d_nohs': svg_data_no_hs }) if save: self.save_data()
def toDataFrame(self, fields=None, molAsImage=True, sketch=True): """ Returns a pandas.DataFrame of the SmallMolLib object. Parameters ---------- fields: list The list of fields to convert into a pandas DataFrame column molAsImage: bool If True, the rdkit.Chem.rdchem.Mol is converted into an image sketch: bool If True, the molecule are rendered to be 2D Returns ------- dataframe: pandas.DataFrame The pandas DataFrame """ from rdkit.Chem import PandasTools from rdkit.Chem.AllChem import Compute2DCoords import pandas as pd from copy import deepcopy if fields is not None: if not isinstance(fields, list): raise TypeError( 'The argument fields passed {} should be a list '.format( type(fields))) else: fields = ['ligname', '_mol'] if molAsImage else ['ligname'] records = [] indexes = [] for i, m in enumerate(self._mols): row = dict((f, m.__getattribute__(f)) for f in fields) if sketch: mm = deepcopy(m._mol) Compute2DCoords(mm) row['_mol'] = mm records.append(row) indexes.append(i) df = pd.DataFrame(records, columns=fields, index=indexes) if molAsImage: Chem.PandasTools.ChangeMoleculeRendering(df) return df
def testMakePNG(self): # smoke test only--that it doesn't fail, not that it looks correct (that's outside the scope of this package) # The choices shown resulted (at last check) in 3 fragments, one of which has a branch try: silent_remove(TEST_PNG) result = create_sample_kmc_result(num_initial_monos=24, max_monos=24, seed=1, max_time=SHORT_TIME) summary = analyze_adj_matrix(result[ADJ_MATRIX]) adj_analysis_to_stdout(summary, break_co_bonds=False) nodes = result[MONO_LIST] adj = result[ADJ_MATRIX] block = generate_mol(adj, nodes) mol = MolFromMolBlock(block) Compute2DCoords(mol) MolToFile(mol, TEST_PNG, size=(2000, 1200)) self.assertTrue(os.path.isfile(TEST_PNG)) finally: silent_remove(TEST_PNG, disable=DISABLE_REMOVE) pass
def display_smiles(smiles_list,colour_type,params,molSize=(450,150)): for smile in smiles_list: highlight =[] colors={} highlightBonds=[] highlightAtomRadii ={} bond_colors={} mol = smile_to_mol(smile, params) mol = Chem.RemoveHs(mol,sanitize = False) if(colour_type=='t'): color = (1,1,0.925) elif(colour_type=='g'): color = (0.925,1,0.925) elif(colour_type=='w'): color = (1,1,1) else: color = (0.925,0.925,1) for i in range(mol.GetNumAtoms()): highlight.append(i) colors[i] = color highlightAtomRadii[i] =1000000 for i in range(mol.GetNumBonds()): highlightBonds.append(i) bond_colors[i] = color Compute2DCoords(mol) drawer = rdMolDraw2D.MolDraw2DCairo(molSize[0],molSize[1]) drawer.DrawMolecule(mol,highlightAtoms=highlight,highlightAtomColors=colors,highlightBonds=highlightBonds,highlightBondColors=bond_colors,highlightAtomRadii=highlightAtomRadii) drawer.FinishDrawing() fp = BytesIO() #with open(fp,'wb') as f: fp.write(drawer.GetDrawingText()) img_top = PIL.Image.open(fp) display(img_top)
def get_batch_from_xls_row(index, row, structure_col, project): if structure_col: smiles_str = row[structure_col] try: struc = Chem.MolFromSmiles(smiles_str) if struc: Compute2DCoords(struc) b = CBHCompoundBatch.objects.from_rd_mol(struc, smiles=smiles_str, project=project, reDraw=True) b.blinded_batch_id = None else: raise Exception("Smiles not processed") except Exception, e: b = CBHCompoundBatch.objects.blinded(project=project) b.original_smiles = smiles_str b.warnings["parseerror"] = "true" b.properties["action"] = "Ignore"
def produce_output(adj_matrix, mono_list, cfg): if cfg[SUPPRESS_SMI] and not (cfg[SAVE_JSON] or cfg[SAVE_PNG] or cfg[SAVE_SVG]): format_list = [SAVE_TCL] mol = None # Make IDE happy else: # Default out is SMILES, which requires getting an rdKit molecule object; also required for everything # except the TCL format format_list = [SAVE_TCL, SAVE_JSON, SAVE_PNG, SAVE_SVG] block = generate_mol(adj_matrix, mono_list) mol = MolFromMolBlock(block) try: smi_str = MolToSmiles(mol) + '\n' except: raise InvalidDataError("Error in producing SMILES string.") # if SMI is to be saved, don't output to stdout if cfg[SAVE_SMI]: fname = create_out_fname(cfg[BASENAME], base_dir=cfg[OUT_DIR], ext=SAVE_SMI) str_to_file(smi_str, fname, print_info=True) else: print("\nSMILES representation: \n", MolToSmiles(mol), "\n") if cfg[SAVE_PNG] or cfg[SAVE_SVG] or cfg[SAVE_JSON]: # PNG and SVG make 2D images and thus need coordinates # JSON will save coordinates--zero's if not computed; might as well compute and save non-zero values Compute2DCoords(mol) for save_format in format_list: if cfg[save_format]: fname = create_out_fname(cfg[BASENAME], base_dir=cfg[OUT_DIR], ext=save_format) if save_format == SAVE_TCL: gen_tcl(adj_matrix, mono_list, tcl_fname=fname, chain_id=cfg[CHAIN_ID], psf_fname=cfg[PSF_FNAME], toppar_dir=cfg[TOPPAR_DIR], out_dir=cfg[OUT_DIR]) if save_format == SAVE_JSON: json_str = MolToJSON(mol) str_to_file(json_str + '\n', fname) elif save_format == SAVE_PNG or save_format == SAVE_SVG: MolToFile(mol, fname, size=cfg[IMAGE_SIZE]) print(f"Wrote file: {fname}")
def depict(self, sketch=True, filename=None, ipython=False, optimize=False, optimizemode='std', removeHs=True, atomlabels=None, highlightAtoms=None, resolution=(400, 200)): """ Depicts the molecules. It is possible to save it into an svg file and also generates a jupiter-notebook rendering Parameters ---------- sketch: bool Set to True for 2D depiction filename: str Set the filename for the svg file ipython: bool Set to True to return the jupiter-notebook rendering optimize: bool Set to True to optimize the conformation. Works only with 3D. optimizemode: ['std', 'mmff'] Set the optimization mode for 3D conformation removeHs: bool Set to True to hide hydrogens in the depiction atomlabels: str Accept any combinations of the following pararemters as unique string '%a%i%c%*' a:atom name, i:atom index, c:atom formal charge (+/-), *:chiral (* if atom is chiral) highlightAtoms: list List of atom to highlight. It can be also a list of atom list, in this case different colors will be used resolution: tuple of integers Resolution in pixels: (X, Y) Returns ------- ipython_svg: SVG object if ipython is set to True Example ------- >>> sm.depict(ipython=True, optimize=True, optimizemode='std') # doctest: +SKIP >>> sm.depict(ipython=True, sketch=True) # doctest: +SKIP >>> sm.depict(ipython=True, sketch=True) # doctest: +SKIP >>> sm.depict(ipython=True, sketch=True, atomlabels="%a%i%c") # doctest: +SKIP >>> ids = np.intersect1d(sm.get('idx', 'hybridization SP2'), sm.get('idx', 'element C')) # doctest: +SKIP >>> sm.depict(ipython=True, sketch=True,highlightAtoms=ids.tolist(), removeHs=False) # doctest: +SKIP """ from rdkit import Chem from rdkit.Chem.AllChem import Compute2DCoords, EmbedMolecule, MMFFOptimizeMolecule, ETKDG from copy import deepcopy if sketch and optimize: raise ValueError('Impossible to use optimization in 2D sketch representation') if optimizemode not in ['std', 'mmff']: raise ValueError('Optimization mode {} not understood. Can be "std" or "ff"'.format(optimizemode)) elements = self._element indexes = self._idx formalcharges = self._formalcharge chirals = self._chiral _mol = deepcopy(self._mol) if sketch: Compute2DCoords(_mol) if removeHs: _mol = Chem.RemoveHs(_mol) elements = self.get('element', 'element H', invert=True) indexes = self.get('idx', 'element H', invert=True) formalcharges = self.get('formalcharge', 'element H', invert=True) chirals = self.get('chiral', 'element H', invert=True) _labelsFunc = ['a', 'i', 'c', '*'] if atomlabels is not None: labels = atomlabels.split('%')[1:] formalcharges = ['' if c == 0 else "+" if c == 1 else "-" for c in formalcharges] chirals = ['' if c == '' else '*' for c in chirals] values = [elements, indexes, formalcharges, chirals] idxs = [_labelsFunc.index(l) for l in labels] labels_required = [values[i] for i in idxs] atomlabels = ["".join([str(i) for i in a]) for a in list(zip(*labels_required))] if optimize: if optimizemode == 'std': EmbedMolecule(_mol, ETKDG()) elif optimizemode == 'mmff': MMFFOptimizeMolecule(_mol) return _depictMol(_mol, filename=filename, ipython=ipython, atomlabels=atomlabels, highlightAtoms=highlightAtoms, resolution=resolution)
def _computeCoords(mol, force=False): if force or (not mol.GetNumConformers() or mol.GetConformer().Is3D()): Compute2DCoords(mol) return mol
def post_validate_list(self, request, **kwargs): """ When a list of SMILES patterns are submitted, save them to elasticsearhc and call the normal validate multi batch function to give the normal statistics page """ session_key = request.COOKIES[settings.SESSION_COOKIE_NAME] deserialized = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) deserialized = self.alter_deserialized_detail_data( request, deserialized) bundle = self.build_bundle(data=dict_strip_unicode_keys(deserialized), request=request) if bundle.obj.pk: self.authorized_update_detail(self.get_object_list(bundle.request), bundle) else: self.authorized_create_detail(self.get_object_list(bundle.request), bundle) smilesdata = bundle.data.get("smilesdata", "") objects = [smi.strip() for smi in smilesdata.splitlines(True)] batches = [] # first assume smiles allmols = [(obj, Chem.MolFromSmiles(str(obj))) for obj in objects] # Next test for inchi multiple_batch = CBHCompoundMultipleBatch.objects.create( project=bundle.data["project"], batch_count=len(allmols)) for index, m in enumerate(allmols): if m[1] is None: inchimol = Chem.MolFromInchi( str(m[0].encode('ascii', 'ignore'))) if inchimol is not None: allmols[index] = (Chem.MolToSmiles(inchimol), inchimol) for m in allmols: if (m[1]): Compute2DCoords(m[1]) batches = [] for mol2 in allmols: if mol2[1]: b = CBHCompoundBatch.objects.from_rd_mol( mol2[1], smiles=mol2[0], project=bundle.data["project"], reDraw=True) else: b = CBHCompoundBatch.objects.blinded( project=bundle.data["project"]) b.warnings["smilesParseError"] = "true" b.properties["action"] = "Ignore" b.original_smiles = mol2[0] b.multiple_batch_id = multiple_batch.pk b.created_by = bundle.request.user.username b.created_by_id = bundle.request.user.id batches.append(b) bundle.data["current_batch"] = multiple_batch.pk bundle.data["headers"] = [] validate_multi_batch(self, multiple_batch, bundle.data, session_key, batches) return self.create_response(request, bundle, response_class=http.HttpAccepted)
def display_encoded_decoded(params,tanimoto_values,encode_decode_mols,num_F2=100,pic_size=(1190/2,1684/2),start_num=1): text_size =12 text_font_size = 12 orange = (255/255,165/255,0) green = (0,1,0) light_blue = (0,1,1) png_files =[] w_len = 1 ''' stop_while = True while stop_while: h_len_min = int(num_F2/w_len)+int(np.mod(num_F2,w_len)>0) h_temp = pic_size[0]/w_len*h_len_min if(h_temp>pic_size[1]) : w_len = w_len+1 else: stop_while = False ''' w_len = 5 h_len_min = int(num_F2/w_len)+int(np.mod(num_F2,w_len)>0) h_len = h_len_min molSize= (int(pic_size[0]/w_len)*2,int(pic_size[0]/w_len)) x = np.array(range(len(libExamples))) #random.shuffle(x) for mol_idx1 in range(h_len*w_len): if( mol_idx1 < num_F2): #mol = Chem.RemoveHs(mol,sanitize = False) mol = Chem.RemoveHs(encode_decode_mols[mol_idx1][0],sanitize = False) Compute2DCoords(mol) drawer = rdMolDraw2D.MolDraw2DCairo(molSize[0],int(molSize[1]/2)*2) drawer.DrawMolecule(mol) drawer.FinishDrawing() fp = BytesIO() #with open(fp,'wb') as f: fp.write(drawer.GetDrawingText()) img_top = PIL.Image.open(fp) mol = Chem.RemoveHs(encode_decode_mols[mol_idx1][1],sanitize = False) Compute2DCoords(mol) drawer = rdMolDraw2D.MolDraw2DCairo(molSize[0],int(molSize[1]/2)*2) drawer.DrawMolecule(mol) drawer.FinishDrawing() fp = BytesIO() #with open(fp,'wb') as f: fp.write(drawer.GetDrawingText()) img_bottom = PIL.Image.open(fp) text_works = Image.new('RGB', (molSize[0],text_size), color = (255, 255, 255)) d = ImageDraw.Draw(text_works) d.text((0,0),str(mol_idx1+start_num), font=ImageFont.truetype("arialbd.ttf", text_font_size),fill=(0,0,0)) d.text((0,0),' Tanimoto '+str(int(tanimoto_values[mol_idx1]*100)/100), font=ImageFont.truetype("arial.ttf", text_font_size),fill=(0,0,0)) comb_img = vstack_img(text_works,vstack_img(img_top,img_bottom)) fp1 = BytesIO() comb_img.save(fp1, 'PNG') png_files.append(fp1) #display(comb_img) #print(comb_img.size) ''' img, svg = gen_img_svg_mol(mol,molSize=(500,250)) fp = BytesIO() display(img) print(libExamples['smiles'][mol_idx]) svg2png(bytestring=svg,write_to=fp,scale=1) text_selected_frags_flash = Image.new('RGB', (half_pic_size[0],single_space*2), color = (255, 255, 255)) d = ImageDraw.Draw(text_selected_frags_flash) d.text((0,0), "Bag of sampled first order fragments", font=ImageFont.truetype("arial.ttf", font_size),fill=(0,0,0)) d.text((0,single_space), "Status: Sampling node", font=ImageFont.truetype("arial.ttf", font_size),fill=(0,0,0)) ''' else: fp2 = BytesIO() png_files.append(fp2) #print((int(molSize[1]/2.0)*4)) image = Image.new('RGB', (molSize[0],(int(molSize[1]/2.0)*4)+text_size), color = 'white') draw = ImageDraw.Draw(image) image.save(fp2, 'PNG') #print(image.size) imgs = [ PIL.Image.open(i) for i in png_files ] imgs_comb = [] for y_idx in range(0,h_len): y_idx_list = png_files[y_idx*w_len:w_len+y_idx*w_len] imgs_comb.append( np.hstack( (np.asarray(PIL.Image.open(i) ) for i in y_idx_list ) )) imgs_comb = np.vstack(imgs_comb) imgs_comb = PIL.Image.fromarray( imgs_comb) imgs_comb_size = imgs_comb.size ''' if(imgs_comb_size[0]!=pic_size[0]): fp = BytesIO() image = Image.new('RGB', (pic_size[0]-imgs_comb_size[0],imgs_comb_size[1]), color = 'white') draw = ImageDraw.Draw(image) image.save(fp, 'PNG') imgs_comb=( np.hstack( (np.asarray(i) for i in [imgs_comb,PIL.Image.open(fp)] ) )) imgs_comb = PIL.Image.fromarray( imgs_comb) imgs_comb_size = imgs_comb.size ''' ''' if(imgs_comb_size[1]!=pic_size[1]): fp = BytesIO() image = Image.new('RGB', (pic_size[0],pic_size[1]-imgs_comb_size[1]), color = 'white') draw = ImageDraw.Draw(image) image.save(fp, 'PNG') imgs_comb=( np.vstack( (np.asarray(i) for i in [imgs_comb,PIL.Image.open(fp)] ) )) imgs_comb = PIL.Image.fromarray( imgs_comb) ''' fp = BytesIO() imgs_comb.save( fp,'PNG' ) return imgs_comb
def display_training_data(params,num_F2=80,pic_size=(int(1190*0.9),int(1684*0.9)),train=True): text_size =20 text_font_size = 20 if(train==True): libExamples = pd.read_csv(params['model_dir']+'Experimental_Training_set_NN.csv') libExamples = libExamples.reset_index(drop=True) else: libExamples = pd.read_csv(params['model_dir']+'Experimental_Test_NN.csv') libExamples = libExamples.reset_index(drop=True) orange = (255/255,165/255,0) green = (0,1,0) light_blue = (0,1,1) png_files =[] w_len = 1 stop_while = True while stop_while: h_len_min = int(num_F2/w_len)+int(np.mod(num_F2,w_len)>0) h_temp = pic_size[0]/w_len*h_len_min if(h_temp>pic_size[1]) : w_len = w_len+1 else: stop_while = False h_len = h_len_min molSize= (int(pic_size[0]/w_len),int(pic_size[0]/w_len)) x = np.array(range(len(libExamples))) #random.shuffle(x) for mol_idx1 in range(h_len*w_len): if( mol_idx1 < num_F2): mol_idx = x[mol_idx1] highlight =[] colors={} highlightBonds=[] highlightAtomRadii ={} bond_colors={} mol =smile_to_mol(libExamples['smiles'][mol_idx], params) mol = Chem.RemoveHs(mol,sanitize = False) if(libExamples['metrics'][mol_idx]==1): for i in range(mol.GetNumAtoms()): highlight.append(i) if(libExamples['metrics'][mol_idx]==1): colors[i] = (0.75,1,0.75) else: colors[i] = (1,0.75,0.75) highlightAtomRadii[i] =1000000 for i in range(mol.GetNumBonds()): highlightBonds.append(i) if(libExamples['metrics'][mol_idx]==1): bond_colors[i] = (0.75,1,0.75) else: bond_colors[i] = (1,0.75,0.75) Compute2DCoords(mol) drawer = rdMolDraw2D.MolDraw2DCairo(molSize[0],molSize[1]) drawer.DrawMolecule(mol,highlightAtoms=highlight,highlightAtomColors=colors,highlightBonds=highlightBonds,highlightBondColors=bond_colors,highlightAtomRadii=highlightAtomRadii) drawer.FinishDrawing() fp = BytesIO() #with open(fp,'wb') as f: fp.write(drawer.GetDrawingText()) img_top = PIL.Image.open(fp) if(libExamples['metrics'][mol_idx]==1): text_works = Image.new('RGB', (molSize[0],text_size), color = (191,255,191)) else: text_works = Image.new('RGB', (molSize[0],text_size), color = (255, 255, 255)) d = ImageDraw.Draw(text_works) if((libExamples['ECFP'][mol_idx]==0 and libExamples['metrics'][mol_idx]==1)or(libExamples['ECFP'][mol_idx]==1 and libExamples['metrics'][mol_idx]==0)): symbol = 'E' else: symbol = "" d.text((int(molSize[0]/2)+text_size*0.5,0), symbol, font=ImageFont.truetype("arial.ttf", text_font_size),fill=(0,0,255)) if((libExamples['ChemVAE'][mol_idx]==0 and libExamples['metrics'][mol_idx]==1)or(libExamples['ChemVAE'][mol_idx]==1 and libExamples['metrics'][mol_idx]==0)): symbol = 'C' else: symbol = "" d.text((int(molSize[0]/2)+text_size*1.5,0), symbol, font=ImageFont.truetype("arial.ttf", text_font_size),fill=(0,0,255)) if((libExamples['rnd_FragVAE'][mol_idx]==0 and libExamples['metrics'][mol_idx]==1)or(libExamples['rnd_FragVAE'][mol_idx]==1 and libExamples['metrics'][mol_idx]==0)): symbol = 'R' else: symbol = "" d.text((int(molSize[0]/2)-text_size*0.5,0), symbol, font=ImageFont.truetype("arial.ttf", text_font_size),fill=(0,0,255)) if((libExamples['FragVAE'][mol_idx]==0 and libExamples['metrics'][mol_idx]==1)or(libExamples['FragVAE'][mol_idx]==1 and libExamples['metrics'][mol_idx]==0)): symbol = 'F' else: symbol = "" d.text((int(molSize[0]/2)-text_size*1.5,0),symbol, font=ImageFont.truetype("arial.ttf", text_font_size),fill=(0,0,255)) d.text((0,0),str(mol_idx1+1), font=ImageFont.truetype("arialbd.ttf", text_font_size),fill=(0,0,0)) comb_img = vstack_img(img_top,text_works) fp1 = BytesIO() comb_img.save(fp1, 'PNG') png_files.append(fp1) ''' img, svg = gen_img_svg_mol(mol,molSize=(500,250)) fp = BytesIO() display(img) print(libExamples['smiles'][mol_idx]) svg2png(bytestring=svg,write_to=fp,scale=1) text_selected_frags_flash = Image.new('RGB', (half_pic_size[0],single_space*2), color = (255, 255, 255)) d = ImageDraw.Draw(text_selected_frags_flash) d.text((0,0), "Bag of sampled first order fragments", font=ImageFont.truetype("arial.ttf", font_size),fill=(0,0,0)) d.text((0,single_space), "Status: Sampling node", font=ImageFont.truetype("arial.ttf", font_size),fill=(0,0,0)) ''' else: fp2 = BytesIO() png_files.append(fp2) image = Image.new('RGB', (molSize[0],molSize[1]+text_size), color = 'white') draw = ImageDraw.Draw(image) image.save(fp2, 'PNG') imgs = [ PIL.Image.open(i) for i in png_files ] imgs_comb = [] for y_idx in range(0,h_len): y_idx_list = png_files[y_idx*w_len:w_len+y_idx*w_len] imgs_comb.append( np.hstack( (np.asarray(PIL.Image.open(i) ) for i in y_idx_list ) )) imgs_comb = np.vstack(imgs_comb) imgs_comb = PIL.Image.fromarray( imgs_comb) imgs_comb_size = imgs_comb.size if(imgs_comb_size[0]!=pic_size[0]): fp = BytesIO() image = Image.new('RGB', (pic_size[0]-imgs_comb_size[0],imgs_comb_size[1]), color = 'white') draw = ImageDraw.Draw(image) image.save(fp, 'PNG') imgs_comb=( np.hstack( (np.asarray(i) for i in [imgs_comb,PIL.Image.open(fp)] ) )) imgs_comb = PIL.Image.fromarray( imgs_comb) imgs_comb_size = imgs_comb.size ''' if(imgs_comb_size[1]!=pic_size[1]): fp = BytesIO() image = Image.new('RGB', (pic_size[0],pic_size[1]-imgs_comb_size[1]), color = 'white') draw = ImageDraw.Draw(image) image.save(fp, 'PNG') imgs_comb=( np.vstack( (np.asarray(i) for i in [imgs_comb,PIL.Image.open(fp)] ) )) imgs_comb = PIL.Image.fromarray( imgs_comb) ''' fp = BytesIO() imgs_comb.save( fp,'PNG' ) return imgs_comb
def depict( self, ids=None, sketch=True, filename=None, ipython=False, optimize=False, optimizemode="std", removeHs=True, legends=None, highlightAtoms=None, mols_perrow=3, ): """ Depicts the molecules into a grid. It is possible to save it into an svg file and also generates a jupiter-notebook rendering Parameters ---------- ids: list The index of the molecules to depict sketch: bool Set to True for 2D depiction filename: str Set the filename for the svg file ipython: bool Set to True to return the jupiter-notebook rendering optimize: bool Set to True to optimize the conformation. Works only with 3D. optimizemode: ['std', 'mmff'] Set the optimization mode for 3D conformation removeHs: bool Set to True to hide hydrogens in the depiction legends: str The name to used for each molecule. Can be 'names':the name of themselves; or 'items': a incremental id highlightAtoms: list A List of atom to highligh for each molecule. It can be also a list of atom list, in this case different colors will be used mols_perrow: int The number of molecules to depict per row of the grid Returns ------- ipython_svg: SVG object if ipython is set to True """ from rdkit.Chem.AllChem import ( Compute2DCoords, EmbedMolecule, MMFFOptimizeMolecule, ETKDG, ) from rdkit.Chem import RemoveHs from moleculekit.smallmol.util import depictMultipleMols if sketch and optimize: raise ValueError( "Impossible to use optmization in 2D sketch representation") if legends is not None and legends not in ["names", "items"]: raise ValueError('The "legends" should be "names" or "items"') _smallmols = self.getMols(ids) if ids is None: _mols = [m._mol for m in self._mols] else: _mols = [m._mol for m in self.getMols(ids)] if highlightAtoms is not None: if len(highlightAtoms) != len(_mols): raise ValueError( "The highlightAtoms {} should have the same length of the " "mols {}".format(len(highlightAtoms), len(_mols))) if sketch: for _m in _mols: Compute2DCoords(_m) if removeHs: _mols = [RemoveHs(_m) for _m in _mols] # activate 3D coords optimization if optimize: if optimizemode == "std": for _m in _mols: EmbedMolecule(_m) elif optimizemode == "mmff": for _m in _mols: MMFFOptimizeMolecule(_m, ETKDG()) legends_list = [] if legends == "names": legends_list = [_m.getProp("ligname") for _m in _smallmols] elif legends == "items": legends_list = [str(n + 1) for n in range(len(_smallmols))] return depictMultipleMols( _mols, ipython=ipython, legends=legends_list, highlightAtoms=highlightAtoms, filename=filename, mols_perrow=mols_perrow, )
def update_pertubation_image(self, mol_a_name, mol_b_name, core_smarts=None, save=False, verbosity=0, **kwargs): """ Generate mol images describing a pertubation between the ligand pair :param str mol_a_name: name of the molecule A :param str mol_b_name: name of the molecule B :param str core_smarts: use this smarts as common core :param bool save: automatically save data :param int verbosity: controls verbosity level """ # verbosity = 5 self.ligands_data[mol_a_name].setdefault('images', {}) self.ligands_data[mol_a_name]['images'].setdefault('perturbations', {}) self.ligands_data[mol_b_name].setdefault('images', {}) self.ligands_data[mol_b_name]['images'].setdefault('perturbations', {}) import rdkit.Chem this_mol_a = rdkit.Chem.Mol(self.ligands_data[mol_a_name]['molecule']) this_mol_b = rdkit.Chem.Mol(self.ligands_data[mol_b_name]['molecule']) if core_smarts is None: # Get core_smarts using find_mcs from merge_topologies import find_mcs this_mol_a.RemoveAllConformers() this_mol_b.RemoveAllConformers() core_smarts = find_mcs([this_mol_a, this_mol_b], savestate=self, verbosity=verbosity, **kwargs).smartsString try: # Test whether the correct data structure is already present assert len(self.ligands_data[mol_a_name]['images']['perturbations'] [mol_b_name][core_smarts]) > 0 assert len(self.ligands_data[mol_b_name]['images']['perturbations'] [mol_a_name][core_smarts]) > 0 except (KeyError, AssertionError): # It isn't, go on and create the images os_util.local_print( 'Perturbation images for molecules {} and {} with common core "{}" were not found. ' 'Generating it.'.format(mol_a_name, mol_b_name, core_smarts), msg_verbosity=os_util.verbosity_level.debug, current_verbosity=verbosity) else: return None from rdkit.Chem.Draw import MolDraw2DSVG from rdkit.Chem.AllChem import Compute2DCoords, GenerateDepictionMatching2DStructure core_mol = rdkit.Chem.MolFromSmarts(core_smarts) Compute2DCoords(core_mol) for each_name, each_mol, other_mol in zip([mol_a_name, mol_b_name], [this_mol_a, this_mol_b], [mol_b_name, mol_a_name]): GenerateDepictionMatching2DStructure(each_mol, core_mol, acceptFailure=True) # Draw mol with hydrogens draw_2d_svg = MolDraw2DSVG(300, 150) draw_2d_svg.drawOptions().addStereoAnnotation = True not_common_atoms = [ i.GetIdx() for i in each_mol.GetAtoms() if i.GetIdx() not in each_mol.GetSubstructMatch(core_mol) ] draw_2d_svg.DrawMolecule(each_mol, legend=each_name, highlightAtoms=not_common_atoms) draw_2d_svg.FinishDrawing() svg_data_hs = draw_2d_svg.GetDrawingText() # Draw mol without hydrogens draw_2d_svg = MolDraw2DSVG(300, 150) draw_2d_svg.drawOptions().addStereoAnnotation = True each_mol = rdkit.Chem.RemoveHs(each_mol) not_common_atoms = [ i.GetIdx() for i in each_mol.GetAtoms() if i.GetIdx() not in each_mol.GetSubstructMatch( rdkit.Chem.RemoveHs(core_mol)) ] draw_2d_svg.DrawMolecule(each_mol, legend=each_name, highlightAtoms=not_common_atoms) draw_2d_svg.FinishDrawing() svg_data_nohs = draw_2d_svg.GetDrawingText() perturbation_imgs = self.ligands_data[each_name]['images'][ 'perturbations'] perturbation_imgs.setdefault(other_mol, {})[core_smarts] = { '2d_hs': svg_data_hs, '2d_nohs': svg_data_nohs } if save: self.save_data()