Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- __pycache__/app.cpython-310.pyc +0 -0
- app.py +115 -4
__pycache__/app.cpython-310.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-310.pyc and b/__pycache__/app.cpython-310.pyc differ
|
|
|
app.py
CHANGED
|
@@ -7,9 +7,8 @@ from datetime import datetime
|
|
| 7 |
import gradio as gr
|
| 8 |
import pandas as pd
|
| 9 |
from huggingface_hub import snapshot_download
|
| 10 |
-
|
| 11 |
from rdkit import Chem
|
| 12 |
-
from rdkit.Chem import Descriptors, Crippen, Lipinski, rdMolDescriptors, QED
|
| 13 |
|
| 14 |
|
| 15 |
BUNDLE_REPO = os.getenv("BUNDLE_REPO", "abdullahsamra/egfr-ai-bundle")
|
|
@@ -155,8 +154,8 @@ def score_smiles(smiles_text):
|
|
| 155 |
"Outputs are computational predictions only.",
|
| 156 |
],
|
| 157 |
}
|
| 158 |
-
|
| 159 |
-
return df, response
|
| 160 |
|
| 161 |
|
| 162 |
def get_example_table():
|
|
@@ -423,7 +422,80 @@ def generate_job_demo(num_molecules, return_top_k, docking_mode, generation_back
|
|
| 423 |
return job_summary, df, response, str(csv_path)
|
| 424 |
|
| 425 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
|
|
|
| 427 |
|
| 428 |
loaded_ok, loaded_msg = download_bundle_light()
|
| 429 |
|
|
@@ -466,6 +538,8 @@ Important:
|
|
| 466 |
score_btn = gr.Button("Score SMILES")
|
| 467 |
score_table = gr.Dataframe(label="Results table")
|
| 468 |
score_json = gr.JSON(label="Backend-style JSON response")
|
|
|
|
|
|
|
| 469 |
|
| 470 |
score_btn.click(
|
| 471 |
score_smiles,
|
|
@@ -553,6 +627,43 @@ Generate -> Enrich -> Optional Docking
|
|
| 553 |
outputs=[example_table, example_json],
|
| 554 |
)
|
| 555 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 556 |
with gr.Tab("Docking Contract"):
|
| 557 |
gr.Markdown(
|
| 558 |
"""
|
|
|
|
| 7 |
import gradio as gr
|
| 8 |
import pandas as pd
|
| 9 |
from huggingface_hub import snapshot_download
|
|
|
|
| 10 |
from rdkit import Chem
|
| 11 |
+
from rdkit.Chem import Descriptors, Crippen, Lipinski, rdMolDescriptors, QED, AllChem
|
| 12 |
|
| 13 |
|
| 14 |
BUNDLE_REPO = os.getenv("BUNDLE_REPO", "abdullahsamra/egfr-ai-bundle")
|
|
|
|
| 154 |
"Outputs are computational predictions only.",
|
| 155 |
],
|
| 156 |
}
|
| 157 |
+
csv_path = write_results_csv(df)
|
| 158 |
+
return df, response, csv_path
|
| 159 |
|
| 160 |
|
| 161 |
def get_example_table():
|
|
|
|
| 422 |
return job_summary, df, response, str(csv_path)
|
| 423 |
|
| 424 |
|
| 425 |
+
def write_results_csv(df: pd.DataFrame, filename: str = "score_smiles_results.csv"):
|
| 426 |
+
out_dir = Path("outputs")
|
| 427 |
+
out_dir.mkdir(parents=True, exist_ok=True)
|
| 428 |
+
out_path = out_dir / filename
|
| 429 |
+
df.to_csv(out_path, index=False)
|
| 430 |
+
return str(out_path)
|
| 431 |
+
|
| 432 |
+
|
| 433 |
+
def smiles_to_3d_file(smiles: str, file_format: str = "sdf"):
|
| 434 |
+
smiles = str(smiles).strip()
|
| 435 |
+
file_format = str(file_format).lower().strip()
|
| 436 |
+
|
| 437 |
+
if file_format not in ["sdf", "mol", "pdb"]:
|
| 438 |
+
return None, {
|
| 439 |
+
"status": "error",
|
| 440 |
+
"message": "Unsupported format. Choose sdf, mol, or pdb.",
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 444 |
+
if mol is None:
|
| 445 |
+
return None, {
|
| 446 |
+
"status": "error",
|
| 447 |
+
"input_smiles": smiles,
|
| 448 |
+
"message": "Invalid SMILES.",
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
canonical_smiles = Chem.MolToSmiles(mol, isomericSmiles=True)
|
| 452 |
+
|
| 453 |
+
mol = Chem.AddHs(mol)
|
| 454 |
+
|
| 455 |
+
params = AllChem.ETKDGv3()
|
| 456 |
+
params.randomSeed = 42
|
| 457 |
+
|
| 458 |
+
embed_status = AllChem.EmbedMolecule(mol, params)
|
| 459 |
+
if embed_status != 0:
|
| 460 |
+
return None, {
|
| 461 |
+
"status": "error",
|
| 462 |
+
"input_smiles": smiles,
|
| 463 |
+
"canonical_smiles": canonical_smiles,
|
| 464 |
+
"message": "3D embedding failed.",
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
try:
|
| 468 |
+
AllChem.UFFOptimizeMolecule(mol, maxIters=500)
|
| 469 |
+
optimization_status = "UFF optimized"
|
| 470 |
+
except Exception as e:
|
| 471 |
+
optimization_status = f"UFF optimization failed, using embedded geometry only: {e}"
|
| 472 |
+
|
| 473 |
+
out_dir = Path("outputs/ligands")
|
| 474 |
+
out_dir.mkdir(parents=True, exist_ok=True)
|
| 475 |
+
|
| 476 |
+
safe_name = "ligand_3d"
|
| 477 |
+
out_path = out_dir / f"{safe_name}.{file_format}"
|
| 478 |
+
|
| 479 |
+
if file_format == "sdf":
|
| 480 |
+
writer = Chem.SDWriter(str(out_path))
|
| 481 |
+
writer.write(mol)
|
| 482 |
+
writer.close()
|
| 483 |
+
elif file_format == "mol":
|
| 484 |
+
Chem.MolToMolFile(mol, str(out_path))
|
| 485 |
+
elif file_format == "pdb":
|
| 486 |
+
Chem.MolToPDBFile(mol, str(out_path))
|
| 487 |
+
|
| 488 |
+
meta = {
|
| 489 |
+
"status": "completed",
|
| 490 |
+
"input_smiles": smiles,
|
| 491 |
+
"canonical_smiles": canonical_smiles,
|
| 492 |
+
"file_format": file_format,
|
| 493 |
+
"file_path": str(out_path),
|
| 494 |
+
"optimization_status": optimization_status,
|
| 495 |
+
"note": "This is a generated 3D conformer from SMILES, not a docked protein-ligand pose.",
|
| 496 |
+
}
|
| 497 |
|
| 498 |
+
return str(out_path), meta
|
| 499 |
|
| 500 |
loaded_ok, loaded_msg = download_bundle_light()
|
| 501 |
|
|
|
|
| 538 |
score_btn = gr.Button("Score SMILES")
|
| 539 |
score_table = gr.Dataframe(label="Results table")
|
| 540 |
score_json = gr.JSON(label="Backend-style JSON response")
|
| 541 |
+
score_csv = gr.File(label="Download CSV")
|
| 542 |
+
|
| 543 |
|
| 544 |
score_btn.click(
|
| 545 |
score_smiles,
|
|
|
|
| 627 |
outputs=[example_table, example_json],
|
| 628 |
)
|
| 629 |
|
| 630 |
+
with gr.Tab("SMILES to 3D File"):
|
| 631 |
+
gr.Markdown(
|
| 632 |
+
"""
|
| 633 |
+
Convert a SMILES string into a downloadable 3D ligand file.
|
| 634 |
+
|
| 635 |
+
Supported formats:
|
| 636 |
+
|
| 637 |
+
- SDF
|
| 638 |
+
- MOL
|
| 639 |
+
- PDB
|
| 640 |
+
|
| 641 |
+
Important: this creates a 3D conformer from SMILES. It is not a docked pose inside the EGFR binding pocket.
|
| 642 |
+
"""
|
| 643 |
+
)
|
| 644 |
+
|
| 645 |
+
smiles_3d_input = gr.Textbox(
|
| 646 |
+
label="SMILES",
|
| 647 |
+
value="CCO",
|
| 648 |
+
lines=2,
|
| 649 |
+
)
|
| 650 |
+
|
| 651 |
+
format_input = gr.Radio(
|
| 652 |
+
choices=["sdf", "mol", "pdb"],
|
| 653 |
+
value="sdf",
|
| 654 |
+
label="Output file format",
|
| 655 |
+
)
|
| 656 |
+
|
| 657 |
+
make_3d_btn = gr.Button("Generate 3D ligand file")
|
| 658 |
+
ligand_file = gr.File(label="Download 3D ligand file")
|
| 659 |
+
ligand_meta = gr.JSON(label="3D file metadata")
|
| 660 |
+
|
| 661 |
+
make_3d_btn.click(
|
| 662 |
+
smiles_to_3d_file,
|
| 663 |
+
inputs=[smiles_3d_input, format_input],
|
| 664 |
+
outputs=[ligand_file, ligand_meta],
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
with gr.Tab("Docking Contract"):
|
| 668 |
gr.Markdown(
|
| 669 |
"""
|