Simon Duerr commited on
Commit
965a7b8
1 Parent(s): 4559fd7

add fixed positions

Browse files
Files changed (2) hide show
  1. app.py +168 -37
  2. requirements.txt +2 -0
app.py CHANGED
@@ -26,6 +26,9 @@ import urllib
26
  import jax.numpy as jnp
27
  import tensorflow as tf
28
 
 
 
 
29
  if "/home/user/app/af_backprop" not in sys.path:
30
  sys.path.append("/home/user/app/af_backprop")
31
 
@@ -250,7 +253,9 @@ def setup_proteinmpnn(model_name="v_48_020", backbone_noise=0.00):
250
  )
251
  from protein_mpnn_utils import StructureDataset, StructureDatasetPDB, ProteinMPNN
252
 
253
- device = torch.device("cpu") #torch.device("cuda:0" if (torch.cuda.is_available()) else "cpu") #fix for memory issues
 
 
254
  # ProteinMPNN model name: v_48_002, v_48_010, v_48_020, v_48_030, v_32_002, v_32_010; v_32_020, v_32_030; v_48_010=version with 48 edges 0.10A noise
255
  # Standard deviation of Gaussian noise to add to backbone atoms
256
  hidden_dim = 128
@@ -291,6 +296,61 @@ def get_pdb(pdb_code="", filepath=""):
291
  return f"{pdb_code}.pdb"
292
 
293
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  def update(
295
  inp,
296
  file,
@@ -301,6 +361,7 @@ def update(
301
  sampling_temp,
302
  model_name,
303
  backbone_noise,
 
304
  ):
305
  from protein_mpnn_utils import (
306
  loss_nll,
@@ -316,7 +377,9 @@ def update(
316
  )
317
  from protein_mpnn_utils import StructureDataset, StructureDatasetPDB, ProteinMPNN
318
 
319
- pdb_path = get_pdb(pdb_code=inp, filepath=file)
 
 
320
 
321
  if pdb_path == None:
322
  return "Error processing PDB"
@@ -368,7 +431,11 @@ def update(
368
  omit_AAs_np = np.array([AA in omit_AAs_list for AA in alphabet]).astype(np.float32)
369
 
370
  chain_id_dict = None
371
- fixed_positions_dict = None
 
 
 
 
372
  pssm_dict = None
373
  omit_AA_dict = None
374
  bias_AA_dict = None
@@ -385,6 +452,7 @@ def update(
385
  tied_positions_dict = make_tied_positions_for_homomers(pdb_dict_list)
386
  else:
387
  tied_positions_dict = None
 
388
  chain_id_dict = {}
389
  chain_id_dict[pdb_dict_list[0]["name"]] = (designed_chain_list, fixed_chain_list)
390
  with torch.no_grad():
@@ -629,6 +697,8 @@ def update(
629
  )
630
  seq_list.append(seq + chain_s)
631
  message += f"{line}\n"
 
 
632
  # somehow sequences still contain X, remove again
633
  for i, x in enumerate(seq_list):
634
  for aa in omit_AAs:
@@ -667,10 +737,11 @@ def update(
667
  gr.File.update(value="all_probs_concat.csv", visible=True),
668
  pdb_path,
669
  gr.Dropdown.update(choices=seq_list),
 
670
  )
671
 
672
 
673
- def update_AF(startsequence, pdb, num_recycles):
674
 
675
  # # run alphafold using ray
676
  # plddts, pae, num_res = run_alphafold(
@@ -720,17 +791,19 @@ def update_AF(startsequence, pdb, num_recycles):
720
  plt.colorbar()
721
  plt.xlabel("Scored residue")
722
  plt.ylabel("Aligned residue")
 
 
723
  # doesnt work (likely because too large)
724
  # plotAF_pae = px.imshow(
725
  # pae,
726
  # labels=dict(x="Scored residue", y="Aligned residue", color=""),
727
  # template="simple_white",
728
- # y=np.arange(len(plddts)),
729
  # )
730
  # plotAF_pae.write_html("test.html")
731
  # plotAF_pae.update_layout(title="Predicted Aligned Error", template="simple_white")
732
 
733
- return molecule(pdb, "out.pdb", num_res), plotAF_plddt, plt
734
 
735
 
736
  def read_mol(molpath):
@@ -742,7 +815,7 @@ def read_mol(molpath):
742
  return mol
743
 
744
 
745
- def molecule(pdb, afpdb, num_res):
746
 
747
  rms, input_pdb, aligned_pdb = align_structures(pdb, afpdb, num_res)
748
  mol = read_mol(input_pdb)
@@ -768,10 +841,6 @@ def molecule(pdb, afpdb, num_res):
768
  .p-1{
769
  padding:0.5rem;
770
  }
771
- .flex{
772
- display:flex;
773
- align-items: center;
774
- }
775
  .w-4{
776
  width:1rem;
777
  }
@@ -802,7 +871,7 @@ select{
802
  <label for="startstructure" class="relative inline-flex items-center mb-4 cursor-pointer ">
803
  <input id="startstructure" type="checkbox" class="sr-only peer" checked>
804
  <div class="w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
805
- <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show initial structure</span>
806
  </label>
807
  </div>
808
  <button type="button" class="text-gray-900 bg-white hover:bg-gray-100 border border-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-gray-600 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:hover:bg-gray-700 mr-2 mb-2" id="download">
@@ -814,23 +883,31 @@ select{
814
  <div> RMSD AlphaFold vs. native: """
815
  + f"{rms:.2f}"
816
  + """Å computed using CEAlign on the aligned fragment</div>
817
- <div class="font-medium mt-4"><b>AlphaFold model confidence:</b></div>
818
- <div class="flex space-x-2 py-1"><span class="w-4 h-4"
819
- style="background-color: rgb(0, 83, 214);">&nbsp;</span><span class="legendlabel">Very high
 
 
 
 
820
  (pLDDT &gt; 90)</span></div>
821
- <div class="flex space-x-2 py-1"><span class="w-4 h-4"
822
- style="background-color: rgb(101, 203, 243);">&nbsp;</span><span class="legendlabel">Confident
823
  (90 &gt; pLDDT &gt; 70)</span></div>
824
- <div class="flex space-x-2 py-1"><span class="w-4 h-4"
825
- style="background-color: rgb(255, 219, 19);">&nbsp;</span><span class="legendlabel">Low (70 &gt;
826
  pLDDT &gt; 50)</span></div>
827
- <div class="flex space-x-2 py-1"><span class="w-4 h-4"
828
- style="background-color: rgb(255, 125, 69);">&nbsp;</span><span class="legendlabel">Very low
829
  (pLDDT &lt; 50)</span></div>
830
  <div class="row column legendDesc"> AlphaFold produces a per-residue confidence
831
  score (pLDDT) between 0 and 100. Some regions below 50 pLDDT may be unstructured in isolation.
832
  </div>
833
  </div>
 
 
 
 
 
 
 
834
  <script>
835
  let viewer = null;
836
  let voldata = null;
@@ -859,14 +936,38 @@ select{
859
  return "Blue";
860
  }
861
  };
862
- viewer.getModel(1).setStyle({},{ cartoon: {color:"gray"} })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
  viewer.getModel(0).setStyle({}, { cartoon: { colorfunc: colorAlpha } });
864
  viewer.zoomTo();
865
  viewer.render();
866
  viewer.zoom(0.8, 2000);
867
  viewer.getModel(0).setHoverable({}, true,
868
  function (atom, viewer, event, container) {
869
- console.log(atom)
870
  if (!atom.label) {
871
  atom.label = viewer.addLabel(atom.resn+atom.resi+" pLDDT=" + atom.b, { position: atom, backgroundColor: "mintcream", fontColor: "black" });
872
  }
@@ -881,12 +982,24 @@ select{
881
  $("#sidechain").change(function () {
882
  if (this.checked) {
883
  BB = ["C", "O", "N"]
884
- viewer.getModel(0).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorscheme: "WhiteCarbon", radius: 0.3}, cartoon: { colorfunc: colorAlpha }});
885
- viewer.getModel(1).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorscheme: "WhiteCarbon", radius: 0.3}, cartoon: { color: "gray" }});
 
 
 
 
 
 
 
886
  viewer.render()
887
  } else {
 
888
  viewer.getModel(0).setStyle({cartoon: { colorfunc: colorAlpha }});
889
- viewer.getModel(1).setStyle({cartoon: { color:"gray" }});
 
 
 
 
890
  viewer.render()
891
  }
892
  });
@@ -894,7 +1007,7 @@ select{
894
  $("#startstructure").change(function () {
895
  if (this.checked) {
896
  $("#sidechain").prop( "checked", false );
897
- viewer.getModel(1).setStyle({},{ cartoon: {color:"gray"} })
898
  viewer.getModel(0).setStyle({}, { cartoon: { colorfunc: colorAlpha } });
899
  viewer.render()
900
  } else {
@@ -931,7 +1044,7 @@ select{
931
 
932
 
933
  def set_examples(example):
934
- label, inp, designed_chain, fixed_chain, homomer, num_seqs, sampling_temp = example
935
  return [
936
  label,
937
  inp,
@@ -940,6 +1053,7 @@ def set_examples(example):
940
  homomer,
941
  gr.Slider.update(value=num_seqs),
942
  gr.Radio.update(value=sampling_temp),
 
943
  ]
944
 
945
 
@@ -976,6 +1090,9 @@ with proteinMPNN:
976
  value=0.1,
977
  label="Sampling temperature",
978
  )
 
 
 
979
  with gr.Row():
980
  model_name = gr.Dropdown(
981
  choices=[
@@ -995,6 +1112,17 @@ with proteinMPNN:
995
  gr.Markdown(
996
  "for correct symmetric tying lenghts of homomer chains should be the same"
997
  )
 
 
 
 
 
 
 
 
 
 
 
998
 
999
  btn = gr.Button("Run")
1000
  label = gr.Textbox(label="Label", visible=False)
@@ -1007,17 +1135,17 @@ with proteinMPNN:
1007
  homomer,
1008
  num_seqs,
1009
  sampling_temp,
 
1010
  ],
1011
  samples=[
1012
- ["Homomer design", "1O91", "A,B,C", "", True, 2, 0.1],
1013
- ["Monomer design", "6MRR", "A", "", False, 2, 0.1],
1014
- ["Redesign of Homomer to Heteromer", "3HTN", "A,B", "C", False, 2, 0.1],
 
 
1015
  ],
1016
  )
1017
- gr.Markdown(
1018
- """ Sampling temperature for amino acids, `T=0.0` means taking argmax, `T>>1.0` means sample randomly. Suggested values `0.1, 0.15, 0.2, 0.25, 0.3`. Higher values will lead to more diversity.
1019
- """
1020
- )
1021
 
1022
  gr.Markdown("# Output")
1023
 
@@ -1064,8 +1192,9 @@ with proteinMPNN:
1064
  with gr.Column():
1065
  plotAF_plddt = gr.Plot(label="pLDDT")
1066
  # remove maxh80 class from css
1067
- plotAF_pae = gr.Plot(label="PAE")
1068
  tempFile = gr.Variable()
 
1069
  btn.click(
1070
  fn=update,
1071
  inputs=[
@@ -1078,6 +1207,7 @@ with proteinMPNN:
1078
  sampling_temp,
1079
  model_name,
1080
  backbone_noise,
 
1081
  ],
1082
  outputs=[
1083
  out,
@@ -1087,11 +1217,12 @@ with proteinMPNN:
1087
  all_probs,
1088
  tempFile,
1089
  chosen_seq,
 
1090
  ],
1091
  )
1092
  btnAF.click(
1093
  fn=update_AF,
1094
- inputs=[chosen_seq, tempFile, num_recycles],
1095
  outputs=[mol, plotAF_plddt, plotAF_pae],
1096
  )
1097
  examples.click(fn=set_examples, inputs=examples, outputs=examples.components)
 
26
  import jax.numpy as jnp
27
  import tensorflow as tf
28
 
29
+
30
+ from moleculekit.molecule import Molecule
31
+
32
  if "/home/user/app/af_backprop" not in sys.path:
33
  sys.path.append("/home/user/app/af_backprop")
34
 
 
253
  )
254
  from protein_mpnn_utils import StructureDataset, StructureDatasetPDB, ProteinMPNN
255
 
256
+ device = torch.device(
257
+ "cpu"
258
+ ) # torch.device("cuda:0" if (torch.cuda.is_available()) else "cpu") #fix for memory issues
259
  # ProteinMPNN model name: v_48_002, v_48_010, v_48_020, v_48_030, v_32_002, v_32_010; v_32_020, v_32_030; v_48_010=version with 48 edges 0.10A noise
260
  # Standard deviation of Gaussian noise to add to backbone atoms
261
  hidden_dim = 128
 
296
  return f"{pdb_code}.pdb"
297
 
298
 
299
+ def preprocess_mol(pdb_code="", filepath=""):
300
+ if pdb_code is None or pdb_code == "":
301
+ try:
302
+ mol = Molecule(filepath.name)
303
+ except AttributeError as e:
304
+ return None
305
+ else:
306
+ mol = Molecule(pdb_code)
307
+ mol.write('original.pdb')
308
+ # clean messy files and only include protein itself
309
+ mol.filter("protein")
310
+ # renumber using moleculekit 0...len(protein)
311
+ df = mol.renumberResidues(returnMapping=True)
312
+ # add proteinMPNN index col which used 1..len(chain), 1...len(chain)
313
+ indexes = []
314
+ for chain, g in df.groupby("chain"):
315
+ j = 1
316
+ for i, row in g.iterrows():
317
+ indexes.append(j)
318
+ j += 1
319
+ df["proteinMPNN_index"] = indexes
320
+ mol.write("cleaned.pdb")
321
+ return "cleaned.pdb", df
322
+
323
+ def make_fixed_positions_dict(atomsel, residue_index_df):
324
+ # we use the uploaded file for the selection
325
+ mol = Molecule('original.pdb')
326
+ # use index for selection as resids will change
327
+ selected_residues = mol.get("index",atomsel)
328
+
329
+ # clean up
330
+ mol.filter("protein")
331
+ mol.renumberResidues()
332
+ # based on selected index now get resids
333
+ selected_residues = [str(i) for i in selected_residues]
334
+ if len(selected_residues)==0:
335
+ return None, []
336
+ selected_residues_str = " ".join(selected_residues)
337
+ selected_residues=set(mol.get('resid', sel=f"index {selected_residues_str}"))
338
+
339
+ # use the proteinMPNN index nomenclature to assemble fixed_positions_dict
340
+ fixed_positions_df = residue_index_df[residue_index_df['new_resid'].isin(selected_residues)]
341
+
342
+ chains = set(mol.get('chain', sel="all"))
343
+ fixed_position_dict = {'cleaned':{}}
344
+ #store the selected residues in a list for the visualization later with cleaned.pdb
345
+ selected_residues = list(fixed_positions_df['new_resid'])
346
+
347
+ for c in chains:
348
+ fixed_position_dict['cleaned'][c]=[]
349
+
350
+ for i, row in fixed_positions_df.iterrows():
351
+ fixed_position_dict['cleaned'][row['chain']].append(row['proteinMPNN_index'])
352
+ return fixed_position_dict, selected_residues
353
+
354
  def update(
355
  inp,
356
  file,
 
361
  sampling_temp,
362
  model_name,
363
  backbone_noise,
364
+ atomsel
365
  ):
366
  from protein_mpnn_utils import (
367
  loss_nll,
 
377
  )
378
  from protein_mpnn_utils import StructureDataset, StructureDatasetPDB, ProteinMPNN
379
 
380
+ # pdb_path = get_pdb(pdb_code=inp, filepath=file)
381
+
382
+ pdb_path, mol_index = preprocess_mol(pdb_code=inp, filepath=file)
383
 
384
  if pdb_path == None:
385
  return "Error processing PDB"
 
431
  omit_AAs_np = np.array([AA in omit_AAs_list for AA in alphabet]).astype(np.float32)
432
 
433
  chain_id_dict = None
434
+ if atomsel == "":
435
+ fixed_positions_dict, selected_residues = None, []
436
+ else:
437
+ fixed_positions_dict, selected_residues=make_fixed_positions_dict(atomsel, mol_index)
438
+
439
  pssm_dict = None
440
  omit_AA_dict = None
441
  bias_AA_dict = None
 
452
  tied_positions_dict = make_tied_positions_for_homomers(pdb_dict_list)
453
  else:
454
  tied_positions_dict = None
455
+
456
  chain_id_dict = {}
457
  chain_id_dict[pdb_dict_list[0]["name"]] = (designed_chain_list, fixed_chain_list)
458
  with torch.no_grad():
 
697
  )
698
  seq_list.append(seq + chain_s)
699
  message += f"{line}\n"
700
+
701
+ message += f"\nfixed positions:* {fixed_positions_dict['cleaned']} \n\n*uses CHAIN:[1..len(chain)] residue numbering"
702
  # somehow sequences still contain X, remove again
703
  for i, x in enumerate(seq_list):
704
  for aa in omit_AAs:
 
737
  gr.File.update(value="all_probs_concat.csv", visible=True),
738
  pdb_path,
739
  gr.Dropdown.update(choices=seq_list),
740
+ selected_residues
741
  )
742
 
743
 
744
+ def update_AF(startsequence, pdb, num_recycles,selectedResidues):
745
 
746
  # # run alphafold using ray
747
  # plddts, pae, num_res = run_alphafold(
 
791
  plt.colorbar()
792
  plt.xlabel("Scored residue")
793
  plt.ylabel("Aligned residue")
794
+ plt.savefig("pae_plot.png", dpi=300)
795
+ plt.close()
796
  # doesnt work (likely because too large)
797
  # plotAF_pae = px.imshow(
798
  # pae,
799
  # labels=dict(x="Scored residue", y="Aligned residue", color=""),
800
  # template="simple_white",
801
+ # y=np.arange(len(plddts_val)),
802
  # )
803
  # plotAF_pae.write_html("test.html")
804
  # plotAF_pae.update_layout(title="Predicted Aligned Error", template="simple_white")
805
 
806
+ return molecule(pdb, "out.pdb", num_res, selectedResidues), plotAF_plddt, "pae_plot.png"
807
 
808
 
809
  def read_mol(molpath):
 
815
  return mol
816
 
817
 
818
+ def molecule(pdb, afpdb, num_res, selectedResidues):
819
 
820
  rms, input_pdb, aligned_pdb = align_structures(pdb, afpdb, num_res)
821
  mol = read_mol(input_pdb)
 
841
  .p-1{
842
  padding:0.5rem;
843
  }
 
 
 
 
844
  .w-4{
845
  width:1rem;
846
  }
 
871
  <label for="startstructure" class="relative inline-flex items-center mb-4 cursor-pointer ">
872
  <input id="startstructure" type="checkbox" class="sr-only peer" checked>
873
  <div class="w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
874
+ <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show input structure</span>
875
  </label>
876
  </div>
877
  <button type="button" class="text-gray-900 bg-white hover:bg-gray-100 border border-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-gray-600 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:hover:bg-gray-700 mr-2 mb-2" id="download">
 
883
  <div> RMSD AlphaFold vs. native: """
884
  + f"{rms:.2f}"
885
  + """Å computed using CEAlign on the aligned fragment</div>
886
+ </div>
887
+ <div class="text-sm flex items-start">
888
+ <div class="w-1/2">
889
+
890
+ <div class="font-medium mt-4 flex items-center space-x-2"><b>AF2 model of redesigned sequence</b></div>
891
+ <div>AlphaFold model confidence:</div>
892
+ <div class="flex space-x-2 py-1"><span class="w-4 h-4" style="background-color: rgb(0, 83, 214);">&nbsp;</span><span class="legendlabel">Very high
893
  (pLDDT &gt; 90)</span></div>
894
+ <div class="flex space-x-2 py-1"><span class="w-4 h-4" style="background-color: rgb(101, 203, 243);">&nbsp;</span><span class="legendlabel">Confident
 
895
  (90 &gt; pLDDT &gt; 70)</span></div>
896
+ <div class="flex space-x-2 py-1"><span class="w-4 h-4" style="background-color: rgb(255, 219, 19);">&nbsp;</span><span class="legendlabel">Low (70 &gt;
 
897
  pLDDT &gt; 50)</span></div>
898
+ <div class="flex space-x-2 py-1"><span class="w-4 h-4" style="background-color: rgb(255, 125, 69);">&nbsp;</span><span class="legendlabel">Very low
 
899
  (pLDDT &lt; 50)</span></div>
900
  <div class="row column legendDesc"> AlphaFold produces a per-residue confidence
901
  score (pLDDT) between 0 and 100. Some regions below 50 pLDDT may be unstructured in isolation.
902
  </div>
903
  </div>
904
+ <div class="w-1/2">
905
+ <div class="font-medium mt-4 flex items-center space-x-2"><b>Input structure </b><span class="w-4 h-4 bg-gray-300 inline-flex" ></span></div>
906
+
907
+ <div class="flex space-x-2 py-1"><span class="w-4 h-4" style="background-color:hotpink" >&nbsp;</span><span class="legendlabel">Fixed positions</span></div>
908
+
909
+ </div>
910
+ </div>
911
  <script>
912
  let viewer = null;
913
  let voldata = null;
 
936
  return "Blue";
937
  }
938
  };
939
+ var selectedResidues = """+
940
+ f"{selectedResidues}"
941
+ +"""
942
+ let colors = {}
943
+ for (let i=0; i<"""+str(num_res)+""";i++){
944
+ if (selectedResidues.includes(i)){
945
+ colors[i]="hotpink"
946
+ }else{
947
+ colors[i]="lightgray"
948
+ }}
949
+
950
+ let colorFixedSidechain = function(atom){
951
+ if (selectedResidues.includes(atom.resi)){
952
+ return "hotpink"
953
+ }else if (atom.elem == "O"){
954
+ return "red"
955
+ }else if (atom.elem == "N"){
956
+ return "blue"
957
+ }else if (atom.elem == "S"){
958
+ return "yellow"
959
+ }else{
960
+ return "lightgray"
961
+ }
962
+ }
963
+
964
+ viewer.getModel(1).setStyle({},{ cartoon: {colorscheme:{prop:"resi",map:colors} } })
965
  viewer.getModel(0).setStyle({}, { cartoon: { colorfunc: colorAlpha } });
966
  viewer.zoomTo();
967
  viewer.render();
968
  viewer.zoom(0.8, 2000);
969
  viewer.getModel(0).setHoverable({}, true,
970
  function (atom, viewer, event, container) {
 
971
  if (!atom.label) {
972
  atom.label = viewer.addLabel(atom.resn+atom.resi+" pLDDT=" + atom.b, { position: atom, backgroundColor: "mintcream", fontColor: "black" });
973
  }
 
982
  $("#sidechain").change(function () {
983
  if (this.checked) {
984
  BB = ["C", "O", "N"]
985
+
986
+ if ($("#startstructure").prop("checked")) {
987
+ viewer.getModel(0).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorscheme: "WhiteCarbon", radius: 0.3}, cartoon: { colorfunc: colorAlpha }});
988
+ viewer.getModel(1).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorfunc:colorFixedSidechain, radius: 0.3}, cartoon: {colorscheme:{prop:"resi",map:colors} }});
989
+ }else{
990
+ viewer.getModel(0).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorscheme: "WhiteCarbon", radius: 0.3}, cartoon: { colorfunc: colorAlpha }});
991
+ viewer.getModel(1).setStyle();
992
+ }
993
+
994
  viewer.render()
995
  } else {
996
+ if ($("#startstructure").prop("checked")) {
997
  viewer.getModel(0).setStyle({cartoon: { colorfunc: colorAlpha }});
998
+ viewer.getModel(1).setStyle({cartoon: {colorscheme:{prop:"resi",map:colors} }});
999
+ }else{
1000
+ viewer.getModel(0).setStyle({cartoon: { colorfunc: colorAlpha }});
1001
+ viewer.getModel(1).setStyle();
1002
+ }
1003
  viewer.render()
1004
  }
1005
  });
 
1007
  $("#startstructure").change(function () {
1008
  if (this.checked) {
1009
  $("#sidechain").prop( "checked", false );
1010
+ viewer.getModel(1).setStyle({},{cartoon: {colorscheme:{prop:"resi",map:colors} } })
1011
  viewer.getModel(0).setStyle({}, { cartoon: { colorfunc: colorAlpha } });
1012
  viewer.render()
1013
  } else {
 
1044
 
1045
 
1046
  def set_examples(example):
1047
+ label, inp, designed_chain, fixed_chain, homomer, num_seqs, sampling_temp, atomsel = example
1048
  return [
1049
  label,
1050
  inp,
 
1053
  homomer,
1054
  gr.Slider.update(value=num_seqs),
1055
  gr.Radio.update(value=sampling_temp),
1056
+ atomsel
1057
  ]
1058
 
1059
 
 
1090
  value=0.1,
1091
  label="Sampling temperature",
1092
  )
1093
+ gr.Markdown(""" Sampling temperature for amino acids, `T=0.0` means taking argmax, `T>>1.0` means sample randomly. Suggested values `0.1, 0.15, 0.2, 0.25, 0.3`. Higher values will lead to more diversity.
1094
+ """
1095
+ )
1096
  with gr.Row():
1097
  model_name = gr.Dropdown(
1098
  choices=[
 
1112
  gr.Markdown(
1113
  "for correct symmetric tying lenghts of homomer chains should be the same"
1114
  )
1115
+ gr.Markdown('## Fixed positions')
1116
+ gr.Markdown("""You can fix important positions in the protein. Resid should be specified with the same numbering as in the input pdb file. The fixed residues will be highlighted in the output.
1117
+ The [VMD selection](http://www.ks.uiuc.edu/Research/vmd/vmd-1.9.2/ug/node89.html) synthax is used. You can also select based on ligands or chains in the input structure to specify interfaces to be fixed.
1118
+
1119
+ - <code>within 5 of resid 94</code> All residues that have >1 atom closer than 5 Å to any atom of residue 94
1120
+ - <code>name CA and within 5 of resid 94</code> All residues that have CA atom closer than 5 Å to any atom of residue 94
1121
+ - <code>resid 94 96 119</code> Residues 94, 94 and 119
1122
+ - <code>within 5 of resname ZN</code> All residues with any atom <5 Å of zinc ion
1123
+ - <code>chain A and within 5 of chain B </code> All residues of chain A that are part of the interface with chain B
1124
+ - <code>protein and within 5 of nucleic </code> All residues that bind to DNA (if present in structure)""")
1125
+ atomsel = gr.Textbox(placeholder="Specify atom selection ", label="Fixed positions")
1126
 
1127
  btn = gr.Button("Run")
1128
  label = gr.Textbox(label="Label", visible=False)
 
1135
  homomer,
1136
  num_seqs,
1137
  sampling_temp,
1138
+ atomsel
1139
  ],
1140
  samples=[
1141
+ ["Homomer design", "1O91", "A,B,C", "", True, 2, 0.1,""],
1142
+ ["Monomer design", "6MRR", "A", "", False, 2, 0.1,""],
1143
+ ["Redesign of Homomer to Heteromer", "3HTN", "A,B", "C", False, 2, 0.1, ""],
1144
+ ["Redesign of MID1 scaffold keeping binding site fixed", "3V1C", "A,B", "", False, 2, 0.1, "within 5 of resname ZN"],
1145
+ ["Redesign of DNA binding protein", "3JRD", "A,B", "", False, 2, 0.1, "within 8 of nucleic"],
1146
  ],
1147
  )
1148
+
 
 
 
1149
 
1150
  gr.Markdown("# Output")
1151
 
 
1192
  with gr.Column():
1193
  plotAF_plddt = gr.Plot(label="pLDDT")
1194
  # remove maxh80 class from css
1195
+ plotAF_pae = gr.Image(label="PAE") #gr.Plot(label="PAE")
1196
  tempFile = gr.Variable()
1197
+ selectedResidues = gr.Variable()
1198
  btn.click(
1199
  fn=update,
1200
  inputs=[
 
1207
  sampling_temp,
1208
  model_name,
1209
  backbone_noise,
1210
+ atomsel,
1211
  ],
1212
  outputs=[
1213
  out,
 
1217
  all_probs,
1218
  tempFile,
1219
  chosen_seq,
1220
+ selectedResidues
1221
  ],
1222
  )
1223
  btnAF.click(
1224
  fn=update_AF,
1225
+ inputs=[chosen_seq, tempFile, num_recycles, selectedResidues],
1226
  outputs=[mol, plotAF_plddt, plotAF_pae],
1227
  )
1228
  examples.click(fn=set_examples, inputs=examples, outputs=examples.components)
requirements.txt CHANGED
@@ -19,4 +19,6 @@ ray
19
  tqdm
20
  gradio==3.0.11
21
  protobuf<4
 
 
22
  -f https://storage.googleapis.com/jax-releases/jax_releases.html
 
19
  tqdm
20
  gradio==3.0.11
21
  protobuf<4
22
+ moleculekit
23
+ --use-deprecated=legacy-resolver
24
  -f https://storage.googleapis.com/jax-releases/jax_releases.html