gabboud commited on
Commit
46eb3c3
·
1 Parent(s): 556109a

rename results fields, modularize event handling

Browse files
Files changed (3) hide show
  1. app.py +4 -29
  2. utils/handle_events.py +56 -0
  3. 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
- # New visualize section
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
- visualize_btn = gr.Button("Visualize", 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
- #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
- visualize_btn.click(visualize_selection, inputs=[batch_dropdown, design_dropdown, gen_results], outputs=display_state)
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, "file": file_name, "pdb": mcif_gz_to_pdb_string_gemmi(file_name)})
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 mcif_gz_to_pdb_string_gemmi(file_path: str) -> str:
93
  """
94
- Converts a .mcif.gz file to a PDB-formatted string.
95
-
96
- Args:
97
- file_path (str): Path to the .mcif.gz file.
98
 
99
- Returns:
100
- str: PDB content as string.
 
 
101
 
102
- Requires: pip install gemmi
 
 
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]