1、将一个SMILES转为图像:
A:imagemol如何处理的?(推荐做训练啥的用)
(不太好,因为线太宽,然后原子和键之间的间隙太小)
不过,大多数人都是用的这种方式做的,最好我也是这样
from rdkit import Chem
from rdkit.Chem import Draw
smiles = "CCO"
mol = Chem.MolFromSmiles(smiles)
img = Draw.MolsToGridImage([mol], molsPerRow=1, subImgSize=(256, 256))
img.save("data//1.png")
B:另外一种处理方式(推荐自己看着用)
from rdkit import Chem
from rdkit.Chem.Draw import rdMolDraw2D
def loadSmilesAndSave(opt_smiles, opt_img_save_path):
mol = Chem.MolFromSmiles(opt_smiles)
drawer = rdMolDraw2D.MolDraw2DCairo(256, 256)
opts = rdMolDraw2D.MolDrawOptions()
# 设置杆的粗细
opts.bondLineWidth = 3
# 设置字母的大小
opts.minFontSize = 15
# 设置字母与杆的间距
opts.additionalAtomLabelPadding = 0.2
drawer.SetDrawOptions(opts)
rdMolDraw2D.PrepareAndDrawMolecule(drawer, mol)
drawer.FinishDrawing()
drawer.WriteDrawingText(opt_img_save_path)
opt_img_save_path = "./data/test.png"
opt_smiles = "CC1C=CC=CC1NC(=O)OCC2=C(OC(=C2)[O-])C"
loadSmilesAndSave(opt_smiles, opt_img_save_path)
其他用法:
其中具体的使用方法看:MolDrawOptions() 这个库中,直接在pycharm中点进去,然后搜索“bondLineWidth ”就可以看到很多的参数:
RDKit|使用MolDraw2DCairo模块绘制分子_最会设计的科研狗的博客-CSDN博客_rdkit画分子
2、多核心将csv中的smiles转为image
import argparse
import os
import pandas as pd
from tqdm import tqdm
from rdkit import Chem
from multiprocessing import Pool, cpu_count
from rdkit.Chem import Draw
import shutil
import logging
"""
当图片数量达到百万级时,单一文件夹内文件过多,文件系统索引效率会大幅下降,导致文件读写变慢。
改为每处理200万个文件的时候就换一个子文件夹储存,最终将所有的子文件夹合并在一个主文件夹内,并将所有的子文件夹删除
python utils/smiles2Image_MutiKernel_mutiDir.py \
--csvname data/XXXdata_property_clean.csv \
--outputImageDir data/XXX/images \
--theCsvFirstLineSMILES canonical_smiles --smilesName mol_index
"""
# 配置日志
logging.basicConfig(filename='error_log.txt', level=logging.ERROR)
def draw_molecule(data):
smiles, name, args, sub_folder_path = data
try:
filename = f"{name}.png"
output_img_path = os.path.join(sub_folder_path, filename)
mol = Chem.MolFromSmiles(smiles)
img = Draw.MolToImage(mol, size=(args.theOutputImageResolution, args.theOutputImageResolution))
img.save(output_img_path)
except Exception as e:
logging.error(f"Error processing {name} with SMILES {smiles}: {e}")
def main():
parser = argparse.ArgumentParser(description='csv2image')
parser.add_argument('--dataroot', type=str, default="./", help='data root')
parser.add_argument('--csvname', type=str, default="top50.csv", help='The name of CSV')
parser.add_argument('--smilesName', type=str, default="imageName", help='Smiles的名字,一般会有一列给出这个smiles叫什么,例如1,2,3')
parser.add_argument('--outputImageDir', type=str, default="../data/")
parser.add_argument('--theCsvFirstLineSMILES', type=str, default="smiles", help='CSV你要转换的列名')
parser.add_argument('--theOutputImageResolution', type=int, default=256)
parser.add_argument('--max_files_per_folder', type=int, default=1000000)
args = parser.parse_args()
csv_file_path = os.path.join(args.dataroot, args.csvname)
main_output_dir = os.path.join(args.dataroot, args.outputImageDir)
if not os.path.exists(main_output_dir):
os.makedirs(main_output_dir)
df = pd.read_csv(csv_file_path)
smiles_values = df[args.theCsvFirstLineSMILES].values
smiles_names = df[args.smilesName].values
# 每个子文件夹最多存储200万个文件
max_files_per_folder = args.max_files_per_folder
total_files = len(smiles_values)
folder_count = (total_files // max_files_per_folder) + 1
data = []
for idx, (smiles, name) in enumerate(zip(smiles_values, smiles_names)):
sub_folder_idx = idx // max_files_per_folder
sub_folder_path = os.path.join(main_output_dir, f"sub_folder_{sub_folder_idx}")
if not os.path.exists(sub_folder_path):
os.makedirs(sub_folder_path)
data.append((smiles, name, args, sub_folder_path))
pool_size = cpu_count()
with Pool(pool_size) as pool:
for _ in tqdm(pool.imap_unordered(draw_molecule, data), total=len(data)):
pass
# 处理完毕后,将所有子文件夹内的文件移动到主文件夹,并删除子文件夹
print("正在合并文件夹...")
for sub_folder_idx in range(folder_count):
sub_folder_path = os.path.join(main_output_dir, f"sub_folder_{sub_folder_idx}")
for file_name in os.listdir(sub_folder_path):
shutil.move(os.path.join(sub_folder_path, file_name), os.path.join(main_output_dir, file_name))
# 删除子文件夹
os.rmdir(sub_folder_path)
print("所有图片处理完成,子文件夹已经合并并删除。")
if __name__ == '__main__':
main()
对于这种在线网址的我们可以写一个脚本,让它批量的自动执行,如何自动执行?:从图片中(批量)提取化学/分子结构——使用python进行批量提取(代码示例)_鸾镜朱颜暗换的博客-CSDN博客