import gradio as gr from inference import Inference import PIL from PIL import Image import pandas as pd import random from rdkit import Chem from rdkit.Chem import Draw from rdkit.Chem.Draw import IPythonConsole import shutil import os class DrugGENConfig: submodel='DrugGEN' inference_model="experiments/models/DrugGEN/" sample_num=1000 inf_dataset_file="chembl45_test.pt" inf_raw_file='data/chembl_test.smi' inf_batch_size=1 mol_data_dir='data' features=False act='relu' max_atom=45 dim=128 depth=1 heads=8 mlp_ratio=3 dropout=0. log_sample_step=100 set_seed=True seed=10 correct=True class NoTargetConfig(DrugGENConfig): submodel="NoTarget" dim=128 inference_model="experiments/models/NoTarget/" model_configs = { "DrugGEN": DrugGENConfig(), "NoTarget": NoTargetConfig(), } def function(model_name: str, num_molecules: int, seed_num: int) -> tuple[PIL.Image, pd.DataFrame, str]: ''' Returns: image, score_df, file path ''' if model_name == "DrugGEN-NoTarget": model_name = "NoTarget" config = model_configs[model_name] config.sample_num = num_molecules if config.sample_num > 250: raise gr.Error("You have requested to generate more than the allowed limit of 250 molecules. Please reduce your request to 250 or fewer.") if seed_num is None or seed_num.strip() == "": config.seed = random.randint(0, 10000) else: try: config.seed = int(seed_num) except ValueError: raise gr.Error("The seed must be an integer value!") inferer = Inference(config) scores = inferer.inference() # create scores_df out of this score_df = pd.DataFrame(scores, index=[0]) output_file_path = f'experiments/inference/{model_name}/inference_drugs.txt' new_path = f'{model_name}_denovo_mols.smi' os.rename(output_file_path, new_path) with open(new_path) as f: inference_drugs = f.read() generated_molecule_list = inference_drugs.split("\n")[:-1] rng = random.Random(config.seed) if num_molecules > 12: selected_molecules = rng.choices(generated_molecule_list, k=12) else: selected_molecules = generated_molecule_list selected_molecules = [Chem.MolFromSmiles(mol) for mol in selected_molecules if Chem.MolFromSmiles(mol) is not None] drawOptions = Draw.rdMolDraw2D.MolDrawOptions() drawOptions.prepareMolsBeforeDrawing = False drawOptions.bondLineWidth = 0.5 molecule_image = Draw.MolsToGridImage( selected_molecules, molsPerRow=3, subImgSize=(400, 400), maxMols=len(selected_molecules), # legends=None, returnPNG=False, drawOptions=drawOptions, highlightAtomLists=None, highlightBondLists=None, ) return molecule_image, score_df, new_path with gr.Blocks() as demo: with gr.Row(): with gr.Column(scale=1): gr.Markdown("# DrugGEN: Target Centric De Novo Design of Drug Candidate Molecules with Graph Generative Deep Adversarial Networks") with gr.Row(): gr.Markdown("[![arXiv](https://img.shields.io/badge/arXiv-2302.07868-b31b1b.svg)](https://arxiv.org/abs/2302.07868)") gr.Markdown("[![github-repository](https://img.shields.io/badge/GitHub-black?logo=github)](https://github.com/HUBioDataLab/DrugGEN)") with gr.Accordion("Expand to display information about models", open=False): gr.Markdown(""" ### Model Variations - **DrugGEN** is the default model. The input of the generator is the real molecules (ChEMBL) dataset (to ease the learning process) and the discriminator compares the generated molecules with the real inhibitors of the given target protein. - **DrugGEN-NoTarget** is the non-target-specific version of DrugGEN. This model only focuses on learning the chemical properties from the ChEMBL training dataset. """) model_name = gr.Radio( choices=("DrugGEN", "DrugGEN-NoTarget"), value="DrugGEN", label="Select a model to make inference", info=str("DrugGEN model designs small molecules to target the human AKT1 protein (UniProt id: P31749)." + '\n' + "DrugGEN-NoTarget model designs random drug-like small molecules.") ) num_molecules = gr.Number( label="Number of molecules to generate", precision=0, # integer input minimum=1, value=100, maximum=999999, info="This space runs on a CPU, which may result in slower performance. Generating 200 molecules takes approximately 6 minutes. Therefore, We set a 250-molecule cap. On a GPU, the model can generate 10,000 molecules in the same amount of time. Please check our GitHub repo for running our models on GPU." ) seed_num = gr.Textbox( label="RNG seed value", value=None, info="This is optional, it can be used for reproducibility." ) submit_button = gr.Button( value="Start Generating" ) with gr.Column(scale=2): scores_df = gr.Dataframe( label="Scores", headers=["Runtime (seconds)", "Validity", "Uniqueness", "Novelty (Train)", "Novelty (Inference)"] ) file_download = gr.File( label="Click to download generated molecules", ) image_output = gr.Image( label="Structures of randomly selected de novo molecules from the inference set:" ) submit_button.click(function, inputs=[model_name, num_molecules, seed_num], outputs=[image_output, scores_df, file_download], api_name="inference") #demo.queue(concurrency_count=1) demo.queue() demo.launch()