Spaces:
Running on Zero
Running on Zero
rename results fields, modularize event handling
Browse files- app.py +4 -29
- utils/handle_events.py +56 -0
- utils/pipelines.py +10 -10
app.py
CHANGED
|
@@ -11,7 +11,7 @@ from rfd3.engine import RFD3InferenceConfig, RFD3InferenceEngine
|
|
| 11 |
from utils import download_weights
|
| 12 |
from utils.pipelines import test_rfd3_from_notebook, unconditional_generation
|
| 13 |
#from gradio_molecule3d import Molecule3D
|
| 14 |
-
|
| 15 |
|
| 16 |
download_weights()
|
| 17 |
|
|
@@ -56,7 +56,7 @@ with gr.Blocks(title="RFD3 Test") as demo:
|
|
| 56 |
gen_btn = gr.Button("Run Unconditional Generation")
|
| 57 |
|
| 58 |
|
| 59 |
-
#
|
| 60 |
with gr.Row():
|
| 61 |
batch_dropdown = gr.Dropdown(
|
| 62 |
choices=[],
|
|
@@ -68,46 +68,21 @@ with gr.Blocks(title="RFD3 Test") as demo:
|
|
| 68 |
label="Select Design",
|
| 69 |
visible=True
|
| 70 |
)
|
| 71 |
-
|
| 72 |
|
| 73 |
display_state = gr.Textbox(label="Selected Batch and Design", visible=True)
|
| 74 |
display_state.value = "Please Select a Batch and Design number to show sequence"
|
| 75 |
-
#viewer = Molecule3D(visible=True)
|
| 76 |
|
| 77 |
-
def update_batch_choices(result):
|
| 78 |
-
if result is None:
|
| 79 |
-
return gr.Dropdown(choices = [])
|
| 80 |
-
batches = sorted(list({d["batch"] for d in result}))
|
| 81 |
-
return gr.update(choices=batches, visible=True)
|
| 82 |
|
| 83 |
gen_btn.click(unconditional_generation, inputs=[num_batches, num_designs_per_batch, length], outputs=[gen_directory, gen_results]).then(
|
| 84 |
update_batch_choices,
|
| 85 |
inputs=gen_results,
|
| 86 |
outputs=batch_dropdown)
|
| 87 |
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
def update_designs(batch, result):
|
| 91 |
-
if batch is None:
|
| 92 |
-
return gr.update(choices=[])
|
| 93 |
-
designs = sorted(list({d["design"] for d in result if d["batch"] == batch}))
|
| 94 |
-
return gr.update(choices=designs)
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
batch_dropdown.change(update_designs, inputs=[batch_dropdown, gen_results], outputs=[design_dropdown])
|
| 99 |
design_dropdown.change()
|
| 100 |
-
|
| 101 |
-
def visualize_selection(batch, design, result):
|
| 102 |
-
if batch is None or design is None:
|
| 103 |
-
return gr.update()
|
| 104 |
-
pdb_path= next(d["pdb"] for d in result if d["batch"] == int(batch) and d["design"] == int(design))
|
| 105 |
-
with open(pdb_path, 'r') as f:
|
| 106 |
-
pdb_str = f.read()
|
| 107 |
-
return gr.update(value=f"Selected Batch: {batch}, Design: {design}, saved at {pdb_str}:\n {pdb_str}", visible=True)
|
| 108 |
-
|
| 109 |
|
| 110 |
-
|
| 111 |
|
| 112 |
|
| 113 |
#def load_viewer(batch, design, result):
|
|
|
|
| 11 |
from utils import download_weights
|
| 12 |
from utils.pipelines import test_rfd3_from_notebook, unconditional_generation
|
| 13 |
#from gradio_molecule3d import Molecule3D
|
| 14 |
+
from utils.handle_events import *
|
| 15 |
|
| 16 |
download_weights()
|
| 17 |
|
|
|
|
| 56 |
gen_btn = gr.Button("Run Unconditional Generation")
|
| 57 |
|
| 58 |
|
| 59 |
+
# Section to inspect PDB of generated structures
|
| 60 |
with gr.Row():
|
| 61 |
batch_dropdown = gr.Dropdown(
|
| 62 |
choices=[],
|
|
|
|
| 68 |
label="Select Design",
|
| 69 |
visible=True
|
| 70 |
)
|
| 71 |
+
show_pdb_btn = gr.Button("Show PDB content", visible=True)
|
| 72 |
|
| 73 |
display_state = gr.Textbox(label="Selected Batch and Design", visible=True)
|
| 74 |
display_state.value = "Please Select a Batch and Design number to show sequence"
|
|
|
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
gen_btn.click(unconditional_generation, inputs=[num_batches, num_designs_per_batch, length], outputs=[gen_directory, gen_results]).then(
|
| 78 |
update_batch_choices,
|
| 79 |
inputs=gen_results,
|
| 80 |
outputs=batch_dropdown)
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
batch_dropdown.change(update_designs, inputs=[batch_dropdown, gen_results], outputs=[design_dropdown])
|
| 83 |
design_dropdown.change()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
+
show_pdb_btn.click(show_pdb, inputs=[batch_dropdown, design_dropdown, gen_results], outputs=display_state)
|
| 86 |
|
| 87 |
|
| 88 |
#def load_viewer(batch, design, result):
|
utils/handle_events.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
|
| 3 |
+
def update_batch_choices(result):
|
| 4 |
+
"""
|
| 5 |
+
Update the batch dropdown choices once RFD3 has finished generating structures. results is the output of RFD3.
|
| 6 |
+
Used as event triggered by the completion of RFD3 generation.
|
| 7 |
+
|
| 8 |
+
Parameters:
|
| 9 |
+
----------
|
| 10 |
+
result: list of dicts
|
| 11 |
+
where each dict contains batch number "batch", design number "design", path to cif file "cif_path", and path to pdb file "pdb_path"
|
| 12 |
+
"""
|
| 13 |
+
if result is None:
|
| 14 |
+
return gr.Dropdown(choices = [])
|
| 15 |
+
batches = sorted(list({d["batch"] for d in result}))
|
| 16 |
+
return gr.update(choices=batches, visible=True)
|
| 17 |
+
|
| 18 |
+
def update_designs(batch, result):
|
| 19 |
+
"""
|
| 20 |
+
Update the design dropdown choices once RFD3 has finished generating structures. results is the output of RFD3.
|
| 21 |
+
Used as event triggered by the selection of a batch in the batch dropdown.
|
| 22 |
+
This logic of trigerring the design dropdown update when a batch is selected comes from the reasoning that different batches may have different numbers of designs.
|
| 23 |
+
There is no reason to think that that will be the case since the number of designs per batch is an input to RFD3, but this might still catch some bugs.
|
| 24 |
+
|
| 25 |
+
Parameters:
|
| 26 |
+
----------
|
| 27 |
+
batch: int
|
| 28 |
+
the batch number selected in the batch dropdown, also takes the batch dropdown object when triggered by an event function.
|
| 29 |
+
result: list of dicts
|
| 30 |
+
where each dict contains batch number "batch", design number "design", path to cif file "cif_path", and path to pdb file "pdb_path"
|
| 31 |
+
"""
|
| 32 |
+
if batch is None:
|
| 33 |
+
return gr.update(choices=[])
|
| 34 |
+
designs = sorted(list({d["design"] for d in result if d["batch"] == batch}))
|
| 35 |
+
return gr.update(choices=designs)
|
| 36 |
+
|
| 37 |
+
def show_pdb(batch, design, result):
|
| 38 |
+
"""
|
| 39 |
+
Show the pdb content of the selected batch and design.
|
| 40 |
+
Used as event triggered by the show pdb button, when a batch and design are selected in the dropdowns.
|
| 41 |
+
|
| 42 |
+
Parameters:
|
| 43 |
+
----------
|
| 44 |
+
batch: int
|
| 45 |
+
the batch number selected in the batch dropdown, also takes the batch dropdown object when triggered by an event function.
|
| 46 |
+
design: int
|
| 47 |
+
the design number selected in the design dropdown, also takes the design dropdown object when triggered by an event function.
|
| 48 |
+
result: list of dicts
|
| 49 |
+
where each dict contains batch number "batch", design number "design", path to cif file "cif_path", and path to pdb file "pdb_path"
|
| 50 |
+
"""
|
| 51 |
+
if batch is None or design is None:
|
| 52 |
+
return gr.update()
|
| 53 |
+
pdb_path= next(d["pdb"] for d in result if d["batch"] == int(batch) and d["design"] == int(design))
|
| 54 |
+
with open(pdb_path, 'r') as f:
|
| 55 |
+
pdb_str = f.read()
|
| 56 |
+
return gr.update(value=f"Selected Batch: {batch}, Design: {design}, saved at {pdb_str}:\n {pdb_str}", visible=True)
|
utils/pipelines.py
CHANGED
|
@@ -43,7 +43,6 @@ def test_rfd3_from_notebook():
|
|
| 43 |
return f"Error: {str(e)}"
|
| 44 |
|
| 45 |
|
| 46 |
-
|
| 47 |
# Initialize engine and run generation
|
| 48 |
@spaces.GPU(duration=300)
|
| 49 |
def unconditional_generation(num_batches, num_designs_per_batch, length):
|
|
@@ -72,7 +71,7 @@ def unconditional_generation(num_batches, num_designs_per_batch, length):
|
|
| 72 |
for batch in range(num_batches):
|
| 73 |
for design in range(num_designs_per_batch):
|
| 74 |
file_name = os.path.join(directory, f"_{batch}_model_{design}.cif.gz")
|
| 75 |
-
results.append({"batch": batch, "design": design, "
|
| 76 |
|
| 77 |
print(results)
|
| 78 |
return directory, results
|
|
@@ -89,17 +88,18 @@ def collect_outputs(gen_directory, num_batches, num_designs_per_batch):
|
|
| 89 |
return f"Error: {str(e)}"
|
| 90 |
|
| 91 |
|
| 92 |
-
def
|
| 93 |
"""
|
| 94 |
-
Converts a .mcif.gz file to
|
| 95 |
-
|
| 96 |
-
Args:
|
| 97 |
-
file_path (str): Path to the .mcif.gz file.
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
| 101 |
|
| 102 |
-
|
|
|
|
|
|
|
| 103 |
"""
|
| 104 |
st = gemmi.read_structure(file_path)
|
| 105 |
st.setup_entities() # Recommended for consistent entity handling [web:18]
|
|
|
|
| 43 |
return f"Error: {str(e)}"
|
| 44 |
|
| 45 |
|
|
|
|
| 46 |
# Initialize engine and run generation
|
| 47 |
@spaces.GPU(duration=300)
|
| 48 |
def unconditional_generation(num_batches, num_designs_per_batch, length):
|
|
|
|
| 71 |
for batch in range(num_batches):
|
| 72 |
for design in range(num_designs_per_batch):
|
| 73 |
file_name = os.path.join(directory, f"_{batch}_model_{design}.cif.gz")
|
| 74 |
+
results.append({"batch": batch, "design": design, "cif_path": file_name, "pdb_path": mcif_gz_to_pdb(file_name)})
|
| 75 |
|
| 76 |
print(results)
|
| 77 |
return directory, results
|
|
|
|
| 88 |
return f"Error: {str(e)}"
|
| 89 |
|
| 90 |
|
| 91 |
+
def mcif_gz_to_pdb(file_path: str) -> str:
|
| 92 |
"""
|
| 93 |
+
Converts a .mcif.gz file to pdb and saves it to the same directory. Returns the path to the pdb file.
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
+
Parameters:
|
| 96 |
+
----------
|
| 97 |
+
file_path: str,
|
| 98 |
+
Path to the .mcif.gz file.
|
| 99 |
|
| 100 |
+
Returns
|
| 101 |
+
-------
|
| 102 |
+
str: path to the generated pdb file.
|
| 103 |
"""
|
| 104 |
st = gemmi.read_structure(file_path)
|
| 105 |
st.setup_entities() # Recommended for consistent entity handling [web:18]
|