import time
start_time = time.time()

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
import pandas as pd
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import DataStructs
from rdkit.Chem import Descriptors
from rdkit.Chem import Draw
from rdkit.Chem import RDConfig
import os
import sys
sys.path.append(os.path.join(RDConfig.RDContribDir, 'SA_Score'))
import sascorer

# Function to calculate largest ring size
def get_largest_ring_size(mol):
    cycle_list = mol.GetRingInfo().AtomRings()
    if cycle_list:
        cycle_length = max([len(j) for j in cycle_list])
    else:
        cycle_length = 0
    return cycle_length

# Function to calculate penalized logP
def plogp(smile):
    if smile:
        mol = Chem.MolFromSmiles(smile)
        if mol:
            log_p = Descriptors.MolLogP(mol)
            sas_score = sascorer.calculateScore(mol)
            largest_ring_size = get_largest_ring_size(mol)
            cycle_score = max(largest_ring_size - 6, 0)
            if log_p and sas_score and largest_ring_size:
                p_logp = log_p - sas_score - cycle_score
                return p_logp
    return -100

# Function to calculate Tanimoto similarity
def sim(input_smile, output_smile):
    if input_smile and output_smile:
        input_mol = Chem.MolFromSmiles(input_smile)
        output_mol = Chem.MolFromSmiles(output_smile)
        if input_mol and output_mol:
            input_fp = AllChem.GetMorganFingerprint(input_mol, 2)
            output_fp = AllChem.GetMorganFingerprint(output_mol, 2)
            return DataStructs.TanimotoSimilarity(input_fp, output_fp)
    return None

# Model-based molecular optimization
def optimize_molecule(input_smiles):
    tokenizer = AutoTokenizer.from_pretrained("zjunlp/MolGen-large-opt")
    model = AutoModelForSeq2SeqLM.from_pretrained("zjunlp/MolGen-large-opt")

    mol_input = Chem.MolFromSmiles(input_smiles)
    if not mol_input:
        raise ValueError("Invalid input SMILES")

    sf_input = tokenizer(input_smiles, return_tensors="pt")
    molecules = model.generate(
        input_ids=sf_input["input_ids"],
        attention_mask=sf_input["attention_mask"],
        do_sample=True,
        max_length=100,
        min_length=5,
        top_k=30,
        top_p=1,
        num_return_sequences=10
    )
    smiles_outputs = list(set(tokenizer.decode(g, skip_special_tokens=True).replace(" ", "") for g in molecules))

    # Calculate properties
    input_plogp = plogp(input_smiles)
    plogp_improvements = [plogp(sm) - input_plogp for sm in smiles_outputs]
    similarities = [sim(input_smiles, sm) for sm in smiles_outputs]

    # Filter valid results
    candidates = {
        "candidates": smiles_outputs,
        "improvements": plogp_improvements,
        "similarities": similarities
    }
    df = pd.DataFrame(candidates)
    valid_results = df[(df['improvements'] > 0) & (df['similarities'] > 0.4)]

    # Extract data
    valid_smiles = valid_results["candidates"].tolist()
    valid_improvements = valid_results["improvements"].tolist()
    valid_similarities = valid_results["similarities"].tolist()

    # Visualize molecules
    mols = [Chem.MolFromSmiles(sm) for sm in valid_smiles]
    visualization = Draw.MolsToGridImage(
        mols,
        molsPerRow=4,
        subImgSize=(200, 200),
        legends=[f"ΔpLogP: {round(imp, 2)} | Sim: {round(sim, 2)}"
                 for imp, sim in zip(valid_improvements, valid_similarities)]
    )

    return valid_smiles, valid_improvements, valid_similarities, visualization


input_smiles = "CCO"  # Replace with your SMILES input
valid_smiles, valid_improvements, valid_similarities, visualization = optimize_molecule(input_smiles)

# Save or display the visualization
visualization.save("optimized_molecules.png")


end_time = time.time()
execution_time = end_time - start_time
print(f"Execution time: {execution_time}")



Error displaying widget: model not found
Error displaying widget: model not found
Error displaying widget: model not found
Error displaying widget: model not found
Error displaying widget: model not found
Error displaying widget: model not found
Error displaying widget: model not found
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][C][Branch1]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][C][Branch1]' for input: '[C][C][Branch1]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][#C][\S@]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][#C][\S@]' for input: '[C][#C][\S@]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][Branch1][N]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][Branch1][N]' for input: '[C][Branch1][N]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][=C][#C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][=C][#C]' for input: '[C][=C][#C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [/C@@H1][=C][#S][C][=C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[/C@@H1][=C][#S][C][=C]' for input: '[/C@@H1][=C][#S][C][=C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [#C][=Branch2][#S]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[#C][=Branch2][#S]' for input: '[#C][=Branch2][#S]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [CH1-1][=Branch1][C][NH0][C][#C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[CH1-1][=Branch1][C][NH0][C][#C]' for input: '[CH1-1][=Branch1][C][NH0][C][#C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][C][=C][#S][Ring1][=Branch2]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][C][=C][#S][Ring1][=Branch2]' for input: '[C][C][=C][#S][Ring1][=Branch2]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][C][Branch1]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][C][Branch1]' for input: '[C][C][Branch1]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][#C][\S@]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][#C][\S@]' for input: '[C][#C][\S@]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][Branch1][N]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][Branch1][N]' for input: '[C][Branch1][N]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][=C][#C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][=C][#C]' for input: '[C][=C][#C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [/C@@H1][=C][#S][C][=C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[/C@@H1][=C][#S][C][=C]' for input: '[/C@@H1][=C][#S][C][=C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [#C][=Branch2][#S]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[#C][=Branch2][#S]' for input: '[#C][=Branch2][#S]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [CH1-1][=Branch1][C][NH0][C][#C]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[CH1-1][=Branch1][C][NH0][C][#C]' for input: '[CH1-1][=Branch1][C][NH0][C][#C]'
[14:04:37] SMILES Parse Error: syntax error while parsing: [C][C][=C][#S][Ring1][=Branch2]
[14:04:37] SMILES Parse Error: Failed parsing SMILES '[C][C][=C][#S][Ring1][=Branch2]' for input: '[C][C][=C][#S][Ring1][=Branch2]'
[14:04:37] 

****
Pre-condition Violation
no draw context
Violation occurred on line 214 in file /project/build/temp.linux-x86_64-cpython-39/rdkit/Code/GraphMol/MolDraw2D/MolDraw2DCairo.cpp
Failed Expression: dp_cr
****

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[6], line 106
    102     return valid_smiles, valid_improvements, valid_similarities, visualization
    105 input_smiles = "CCO"  # Replace with your SMILES input
--> 106 valid_smiles, valid_improvements, valid_similarities, visualization = optimize_molecule(input_smiles)
    108 # Save or display the visualization
    109 visualization.save("optimized_molecules.png")

Cell In[6], line 94, in optimize_molecule(input_smiles)
     92 # Visualize molecules
     93 mols = [Chem.MolFromSmiles(sm) for sm in valid_smiles]
---> 94 visualization = Draw.MolsToGridImage(
     95     mols,
     96     molsPerRow=4,
     97     subImgSize=(200, 200),
     98     legends=[f"ΔpLogP: {round(imp, 2)} | Sim: {round(sim, 2)}"
     99              for imp, sim in zip(valid_improvements, valid_similarities)]
    100 )
    102 return valid_smiles, valid_improvements, valid_similarities, visualization

File /opt/app-root/lib64/python3.9/site-packages/rdkit/Chem/Draw/IPythonConsole.py:268, in ShowMols(mols, maxMols, **kwargs)
    265 if "drawOptions" not in kwargs:
    266   kwargs["drawOptions"] = drawOptions
--> 268 res = fn(mols, **kwargs)
    269 if InteractiveRenderer.isEnabled():
    270   return HTML(res)

File /opt/app-root/lib64/python3.9/site-packages/rdkit/Chem/Draw/__init__.py:622, in MolsToGridImage(mols, molsPerRow, subImgSize, legends, highlightAtomLists, highlightBondLists, useSVG, returnPNG, **kwargs)
    618   return _MolsToGridSVG(mols, molsPerRow=molsPerRow, subImgSize=subImgSize, legends=legends,
    619                         highlightAtomLists=highlightAtomLists,
    620                         highlightBondLists=highlightBondLists, **kwargs)
    621 else:
--> 622   return _MolsToGridImage(mols, molsPerRow=molsPerRow, subImgSize=subImgSize, legends=legends,
    623                           highlightAtomLists=highlightAtomLists,
    624                           highlightBondLists=highlightBondLists, returnPNG=returnPNG, **kwargs)

File /opt/app-root/lib64/python3.9/site-packages/rdkit/Chem/Draw/__init__.py:571, in _MolsToGridImage(mols, molsPerRow, subImgSize, legends, highlightAtomLists, highlightBondLists, drawOptions, returnPNG, **kwargs)
    569     res = _drawerToImage(d2d)
    570   else:
--> 571     res = d2d.GetDrawingText()
    573 return res

RuntimeError: Pre-condition Violation
	no draw context
	Violation occurred on line 214 in file Code/GraphMol/MolDraw2D/MolDraw2DCairo.cpp
	Failed Expression: dp_cr
	RDKIT: 2022.09.5
	BOOST: 1_78
​


this is where i lifed the code by removing some parts 

import gradio as gr
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
import pandas as pd
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import DataStructs
from rdkit.Chem import Descriptors
from rdkit.Chem import Draw
import selfies as sf
from rdkit.Chem import RDConfig
import os
import sys
sys.path.append(os.path.join(RDConfig.RDContribDir, 'SA_Score'))
import sascorer



def get_largest_ring_size(mol):
    cycle_list = mol.GetRingInfo().AtomRings()
    if cycle_list:
        cycle_length = max([len(j) for j in cycle_list])
    else:
        cycle_length = 0
    return cycle_length

def plogp(smile):
    if smile:
        mol = Chem.MolFromSmiles(smile)
        if mol:
            log_p = Descriptors.MolLogP(mol)
            sas_score = sascorer.calculateScore(mol)
            largest_ring_size = get_largest_ring_size(mol)
            cycle_score = max(largest_ring_size - 6, 0)
            if log_p and sas_score and largest_ring_size:
                p_logp = log_p - sas_score - cycle_score
                return p_logp
            else: 
                return -100
        else:
            return -100
    else:
        return -100
    
def sf_decode(selfies):
    try:
        decode = sf.decoder(selfies)
        return decode
    except sf.DecoderError:
        return ''
    
def sim(input_smile, output_smile):
    if input_smile and output_smile:
        input_mol = Chem.MolFromSmiles(input_smile)
        output_mol = Chem.MolFromSmiles(output_smile)
        if input_mol and output_mol:
            input_fp = AllChem.GetMorganFingerprint(input_mol, 2)
            output_fp = AllChem.GetMorganFingerprint(output_mol, 2)
            sim = DataStructs.TanimotoSimilarity(input_fp, output_fp)
            return sim
        else: return None
    else: return None 


def gen_process(gen_input):
    tokenizer = AutoTokenizer.from_pretrained("zjunlp/MolGen-large")
    model = AutoModelForSeq2SeqLM.from_pretrained("zjunlp/MolGen-large")
    
    sf_input = tokenizer(gen_input, return_tensors="pt")
    
    # beam search
    molecules = model.generate(input_ids=sf_input["input_ids"],
                              attention_mask=sf_input["attention_mask"],
                              max_length=15,
                              min_length=5,
                              num_return_sequences=4,
                              num_beams=5)

    gen_output = [tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=True).replace(" ","") for g in molecules]
    smis = [sf.decoder(i) for i in gen_output]
    mols = []
    for smi in smis:
        mol = Chem.MolFromSmiles(smi)
        mols.append(mol)
    
    gen_output_image = Draw.MolsToGridImage(
        mols,
        molsPerRow=4,
        subImgSize=(200,200),
        legends=['' for x in mols]
    )
    
    return "\n".join(gen_output), gen_output_image
 
def opt_process(opt_input):

    tokenizer = AutoTokenizer.from_pretrained("zjunlp/MolGen-large-opt")
    model = AutoModelForSeq2SeqLM.from_pretrained("zjunlp/MolGen-large-opt")
    
    input = opt_input

    smis_input = sf.decoder(input)
    mol_input = []
    mol = Chem.MolFromSmiles(smis_input)
    mol_input.append(mol)
    
    opt_input_img = Draw.MolsToGridImage(
        mol_input,
        molsPerRow=4,
        subImgSize=(200,200),
        legends=['' for x in mol_input]
    )
    
    sf_input = tokenizer(input, return_tensors="pt")
    molecules = model.generate(
                    input_ids=sf_input["input_ids"],
                    attention_mask=sf_input["attention_mask"],
                    do_sample=True,
                    max_length=100,
                    min_length=5,
                    top_k=30,
                    top_p=1,
                    num_return_sequences=10
                    )
    sf_output = [tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=True).replace(" ","") for g in molecules]
    sf_output = list(set(sf_output))
    input_sm = sf_decode(input)
    sm_output = [sf_decode(sf) for sf in sf_output]
    
    
    input_plogp = plogp(input_sm)
    plogp_improve = [plogp(i)-input_plogp for i in sm_output]
    
    
    simm = [sim(i,input_sm) for i in sm_output]
    
    candidate_selfies = {"candidates": sf_output, "improvement": plogp_improve, "sim": simm}
    data = pd.DataFrame(candidate_selfies)
    
    results = data[(data['improvement']> 0) & (data['sim']>0.4)]
    opt_output  = results["candidates"].tolist()
    opt_output_imp = results["improvement"].tolist()
    opt_output_imp = [str(i) for i in opt_output_imp]
    opt_output_sim = results["sim"].tolist()
    opt_output_sim = [str(i) for i in opt_output_sim]
    

    smis = [sf.decoder(i) for i in opt_output]
    mols = []
    for smi in smis:
        mol = Chem.MolFromSmiles(smi)
        mols.append(mol)
    
    opt_output_img = Draw.MolsToGridImage(
        mols,
        molsPerRow=4,
        subImgSize=(200,200),
        legends=['' for x in mols]
    )
    return opt_input_img, "\n".join(opt_output), "\n".join(opt_output_imp), "\n".join(opt_output_sim), opt_output_img

with gr.Blocks() as demo:
    gr.Markdown("# MolGen: Domain-Agnostic Molecular Generation with Self-feedback")

    with gr.Tabs():
        with gr.TabItem("Molecular Generation"):
            with gr.Row():
                with gr.Column():
                    gen_input = gr.Textbox(label="Input", lines=1, placeholder="SELFIES Input")
                    gen_button = gr.Button("Generate")

                with gr.Column():
                    gen_output = gr.Textbox(label="Generation Results", lines=5, placeholder="")
                    gen_output_image = gr.Image(label="Visualization")
       
            gr.Examples(
                examples=[["[C][=C][C][=C][C][=C][Ring1][=Branch1]"], 
                          ["[C]"]
                          ],
                inputs=[gen_input],
                outputs=[gen_output, gen_output_image],
                fn=gen_process,
                cache_examples=True,
            )

        with gr.TabItem("Constrained Molecular Property Optimization"):
            with gr.Row():
                with gr.Column():
                    opt_input = gr.Textbox(label="Input", lines=1, placeholder="SELFIES Input")
                    opt_button = gr.Button("Optimize")

                with gr.Column():
                    opt_input_img = gr.Image(label="Input Visualization")
                    opt_output = gr.Textbox(label="Optimization Results", lines=3, placeholder="")
                    opt_output_imp = gr.Textbox(label="Optimization Property Improvements", lines=3, placeholder="")
                    opt_output_sim = gr.Textbox(label="Similarity", lines=3, placeholder="")
                    opt_output_img = gr.Image(label="Output Visualization")
                    

            gr.Examples(
                examples=[["[C][C][=Branch1][C][=O][N][C][C][O][C][C][O][C][C][O][C][C][Ring1][N]"], 
                          ["[C][C][S][C][C][S][C][C][C][S][C][C][S][C][Ring1][=C]"],
                          ["[N][#C][C][C][C@@H1][C][C][C][C][C][C][C][C][C][C][C][Ring1][N][=O]"]
                          ],
                inputs=[opt_input],
                outputs=[opt_input_img, opt_output, opt_output_imp, opt_output_sim, opt_output_img],
                fn=opt_process,
                cache_examples=True,
            )

    gen_button.click(fn=gen_process, inputs=[gen_input], outputs=[gen_output, gen_output_image])
    opt_button.click(fn=opt_process, inputs=[opt_input], outputs=[opt_input_img, opt_output, opt_output_imp, opt_output_sim, opt_output_img])

demo.launch()