Simon Duerr commited on
Commit
88dc70f
1 Parent(s): 1c9254d
Files changed (4) hide show
  1. README.md +5 -1
  2. app.py +132 -31
  3. moleculekit-1.1.1.tar.gz +0 -3
  4. utils/voxelization.py +3 -3
README.md CHANGED
@@ -4,10 +4,14 @@ emoji: 👀
4
  colorFrom: indigo
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 3.0.10
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces#reference
 
 
 
 
 
4
  colorFrom: indigo
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 3.0.11
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces#reference
14
+
15
+
16
+ Moleculekit is a product of Acellera https://github.com/Acellera/moleculekit and distributed under
17
+ the HTMD Software License and free for Academics.
app.py CHANGED
@@ -52,19 +52,26 @@ def update(inp, file, mode, custom_resids, clustering_threshold):
52
  return "pdb code must be 4 letters or Uniprot code does not match", ""
53
  identifier = os.path.basename(filepath)
54
  if mode == "All residues":
 
55
  ids = get_all_protein_resids(filepath)
56
  elif len(custom_resids)!=0:
 
57
  ids=get_all_resids_from_list(filepath,custom_resids.replace(","," "))
58
  else:
 
59
  ids = get_all_metalbinding_resids(filepath)
60
-
61
- voxels, prot_centers, prot_N, prots = processStructures(filepath, ids)
 
 
 
 
62
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
63
  voxels.to(device)
64
- print(voxels.shape)
65
  model = Model()
66
  model.to(device)
67
- model.load_state_dict(torch.load("weights/metal_0.5A_v3_d0.2_16Abox.pth", map_location=torch.device('cpu')))
68
  model.eval()
69
  with warnings.catch_warnings():
70
  warnings.filterwarnings("ignore")
@@ -100,21 +107,6 @@ def update(inp, file, mode, custom_resids, clustering_threshold):
100
  )
101
 
102
 
103
- def test():
104
- x = """<!DOCTYPE html>
105
- <html>
106
- <head>
107
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
108
- </head>
109
- <body>
110
- <script src="https://3Dmol.org/build/3Dmol-min.js" async></script> <div style="height: 400px; width: 400px; position: relative;" class="viewer_3Dmoljs" data-pdb="2POR" data-backgroundcolor="0xffffff" data-style="stick" ></div>
111
- </body></html>"""
112
- return f"""<iframe style="width: 100%; height: 480px" name="result" allow="midi; geolocation; microphone; camera;
113
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
114
- allow-scripts allow-same-origin allow-popups
115
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
116
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
117
-
118
 
119
  def read_mol(molpath):
120
  with open(molpath, "r") as fp:
@@ -134,13 +126,14 @@ def molecule(pdb, probes, cube):
134
  <html>
135
  <head>
136
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
 
137
  <style>
138
  body{
139
  font-family:sans-serif
140
  }
141
  .mol-container {
142
  width: 100%;
143
- height: 400px;
144
  position: relative;
145
  }
146
  .slider{
@@ -160,16 +153,50 @@ def molecule(pdb, probes, cube):
160
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.3/rangeslider.min.js" integrity="sha512-BUlWdwDeJo24GIubM+z40xcj/pjw7RuULBkxOTc+0L9BaGwZPwiwtbiSVzv31qR7TWx7bs6OPTE5IyfLOorboQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
161
  </head>
162
  <body>
163
- <div class="slidercontainer">
164
  <span>Isovalue </span>
165
  <span id="isovalue">0.5</span>
166
- <input class="slider" type="range" id="rangeslider" min="0" max="1" step="0.025" value=0.5>
167
  </div>
168
 
169
  <div id="container" class="mol-container"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  <script>
171
  let viewer = null;
172
  let voldata = null;
 
 
 
173
  $(document).ready(function () {
174
  let element = $("#container");
175
  let config = { backgroundColor: "white" };
@@ -184,8 +211,8 @@ def molecule(pdb, probes, cube):
184
  + cubefile
185
  + """`
186
  voldata = new $3Dmol.VolumeData(cubefile, "cube");
187
- viewer.addIsosurface(voldata, { isoval: 0.7 , color: "blue", alpha: 0.85, smoothness: 1 });
188
- viewer.getModel(0).setStyle({}, {cartoon: {color: "grayCarbon"}});
189
  let probes =`"""
190
  + probes
191
  + """`
@@ -207,25 +234,90 @@ def molecule(pdb, probes, cube):
207
  viewer.zoomTo();
208
  viewer.render();
209
  viewer.zoom(0.8, 2000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  </script>
212
  <script>
213
  $("#rangeslider").rangeslider().on("change", function (el) {
214
  isoval = parseFloat(el.target.value);
215
  $("#isovalue").text(el.target.value)
216
- viewer.addIsosurface(voldata, { isoval: parseFloat(el.target.value), color: "blue", alpha: 0.85, smoothness: 1 });
 
 
 
217
  viewer.render();
218
  });
219
  </script>
220
  </body></html>"""
221
  )
222
 
223
- return f"""<iframe style="width: 100%; height: 480px" name="result" allow="midi; geolocation; microphone; camera;
224
  display-capture; encrypted-media;" sandbox="allow-modals allow-forms
225
  allow-scripts allow-same-origin allow-popups
226
  allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
227
  allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
228
 
 
 
 
 
 
 
 
229
 
230
  metal3d = gr.Blocks()
231
 
@@ -248,16 +340,25 @@ with metal3d:
248
  clustering_threshold = gr.Slider(minimum=0.15,maximum=1, value=0.15,step=0.05, label="Clustering threshold")
249
  distance_cutoff = gr.Slider(minimum=1,maximum=10, value=7,step=1, label="Clustering distance cutoff")
250
  btn = gr.Button("Run")
251
- gr.Markdown(
252
- """ <small>Inference using CPU-only, can be quite slow for more than 20 residues. Use Colab notebook for GPU acceleration</small>
253
- """
254
- )
 
 
 
 
 
 
 
 
255
 
256
 
257
  gr.Markdown("# Output")
 
258
  out = gr.Textbox(label="status")
259
  mol = gr.HTML()
260
  btn.click(fn=update, inputs=[inp, file, mode, custom_resids, clustering_threshold], outputs=[out, mol])
261
 
262
- metal3d.launch()
263
 
 
52
  return "pdb code must be 4 letters or Uniprot code does not match", ""
53
  identifier = os.path.basename(filepath)
54
  if mode == "All residues":
55
+ print('using all residues')
56
  ids = get_all_protein_resids(filepath)
57
  elif len(custom_resids)!=0:
58
+ print('using listed residues', custom_resids)
59
  ids=get_all_resids_from_list(filepath,custom_resids.replace(","," "))
60
  else:
61
+ print('using metalbinding')
62
  ids = get_all_metalbinding_resids(filepath)
63
+ print(filepath)
64
+ print(ids)
65
+ try:
66
+ voxels, prot_centers, prot_N, prots = processStructures(filepath, ids)
67
+ except Exception as e:
68
+ return "Error", f"""<div class="text-center mt-4"> Something went wrong with the voxelization, reset custom residues and other input fiels and check error message <br> <br> <code>{e}</code></div>"""
69
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
70
  voxels.to(device)
71
+
72
  model = Model()
73
  model.to(device)
74
+ model.load_state_dict(torch.load("weights/metal_0.5A_v3_d0.2_16Abox.pth", map_location=torch.device("cuda" if torch.cuda.is_available() else "cpu")))
75
  model.eval()
76
  with warnings.catch_warnings():
77
  warnings.filterwarnings("ignore")
 
107
  )
108
 
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
  def read_mol(molpath):
112
  with open(molpath, "r") as fp:
 
126
  <html>
127
  <head>
128
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
129
+ <link rel="stylesheet" href="https://unpkg.com/flowbite@1.4.5/dist/flowbite.min.css" />
130
  <style>
131
  body{
132
  font-family:sans-serif
133
  }
134
  .mol-container {
135
  width: 100%;
136
+ height: 600px;
137
  position: relative;
138
  }
139
  .slider{
 
153
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.3/rangeslider.min.js" integrity="sha512-BUlWdwDeJo24GIubM+z40xcj/pjw7RuULBkxOTc+0L9BaGwZPwiwtbiSVzv31qR7TWx7bs6OPTE5IyfLOorboQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
154
  </head>
155
  <body>
156
+ <div class="slidercontainer my-8">
157
  <span>Isovalue </span>
158
  <span id="isovalue">0.5</span>
159
+ <input class="slider text-blue-400" type="range" id="rangeslider" min="0" max="1" step="0.05" value=0.5>
160
  </div>
161
 
162
  <div id="container" class="mol-container"></div>
163
+
164
+ <div class="flex items-center justify-center my-4">
165
+ <div class="px-4">
166
+ <label for="sidechain" class="relative inline-flex items-center mb-4 cursor-pointer ">
167
+ <input id="sidechain"type="checkbox" class="sr-only peer">
168
+ <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>
169
+ <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show side chains</span>
170
+ </label>
171
+ </div>
172
+ <div class="px-4">
173
+ <label for="pdbmetal" class="relative inline-flex items-center mb-4 cursor-pointer ">
174
+ <input id="pdbmetal" type="checkbox" class="sr-only peer" checked>
175
+ <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>
176
+ <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show PDB metals</span>
177
+ </label>
178
+ </div>
179
+ <div class="px-4">
180
+ <label for="probes" class="relative inline-flex items-center mb-4 cursor-pointer ">
181
+ <input id="probes" type="checkbox" class="sr-only peer" checked>
182
+ <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>
183
+ <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Show Probes</span>
184
+ </label>
185
+ </div>
186
+ </div>
187
+
188
+ <div class="flex items-center justify-center my-4">
189
+ <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">
190
+ <svg class="w-6 h-6 mr-2 -ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
191
+ Download predictions
192
+ </button>
193
+ </div>
194
  <script>
195
  let viewer = null;
196
  let voldata = null;
197
+ let shape = null;
198
+ let sidechain = null;
199
+ let metal = null;
200
  $(document).ready(function () {
201
  let element = $("#container");
202
  let config = { backgroundColor: "white" };
 
211
  + cubefile
212
  + """`
213
  voldata = new $3Dmol.VolumeData(cubefile, "cube");
214
+ shape = viewer.addIsosurface(voldata, { isoval: 0.5 , color: "blue", alpha: 0.85, smoothness: 1 });
215
+ viewer.getModel(0).setStyle({}, {cartoon: {}});
216
  let probes =`"""
217
  + probes
218
  + """`
 
234
  viewer.zoomTo();
235
  viewer.render();
236
  viewer.zoom(0.8, 2000);
237
+
238
+ $("#sidechain").change(function () {
239
+ if (this.checked) {
240
+ BB = ["C", "O", "N"]
241
+ viewer.getModel(0).setStyle( {"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {hidden:false, colorscheme: "WhiteCarbon", radius: 0.3}, cartoon: {}});
242
+ viewer.render()
243
+ $("#pdbmetal").prop( "checked", false );
244
+ } else {
245
+ BB = ["C", "O", "N"]
246
+ viewer.getModel(0).setStyle({"and": [{resn: ["GLY", "PRO"], invert: true},{atom: BB, invert: true},]},{stick: {colorscheme: "WhiteCarbon",hidden:true, radius: 0.3}, cartoon: {}});
247
+ viewer.render()
248
+ $("#pdbmetal").prop( "checked", false );
249
+ }
250
+
251
+ });
252
+ $("#pdbmetal").change(function () {
253
+ if (this.checked) {
254
+ viewer.getModel(0).setStyle({ "resn": ["ZN","MG","NA","FE", "NI","MN","CA", "CU", "CU1"] }, { "sphere": {hidden:false}});
255
+ viewer.render()
256
+ } else {
257
+ viewer.getModel(0).setStyle({ "resn": ["ZN","MG","NA","FE","NI", "MN","CA", "CU", "CU1"] }, { "sphere": {hidden:true}});
258
+ viewer.render()
259
+ }
260
+ });
261
+ $("#probes").change(function () {
262
+ if (this.checked) {
263
+ viewer.getModel(1).setStyle({ "resn": "ZN" }, { "sphere": { }});
264
+ viewer.addStyle()
265
+ viewer.render()
266
+ } else {
267
+ viewer.getModel(1).setStyle({});
268
+ viewer.render()
269
+ }
270
+ });
271
+
272
+ $("#download").click(function () {
273
+ download("protein.pdb", data);
274
+ download("metaldensity.cube", cubefile);
275
+ download("probes.pdb", probes);
276
+ })
277
+
278
  });
279
+
280
+ function download(filename, text) {
281
+ var element = document.createElement("a");
282
+ element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
283
+ element.setAttribute("download", filename);
284
+
285
+ element.style.display = "none";
286
+ document.body.appendChild(element);
287
+
288
+ element.click();
289
+
290
+ document.body.removeChild(element);
291
+ }
292
+
293
  </script>
294
  <script>
295
  $("#rangeslider").rangeslider().on("change", function (el) {
296
  isoval = parseFloat(el.target.value);
297
  $("#isovalue").text(el.target.value)
298
+ console.log("Change isosurface to "+el.target.value)
299
+ viewer.removeShape(shape)
300
+ shape=viewer.addIsosurface(voldata, { isoval: parseFloat(el.target.value), color: "blue", alpha: 0.85, smoothness: 1 });
301
+
302
  viewer.render();
303
  });
304
  </script>
305
  </body></html>"""
306
  )
307
 
308
+ return f"""<iframe style="width: 100%; height: 1000px" name="result" allow="midi; geolocation; microphone; camera;
309
  display-capture; encrypted-media;" sandbox="allow-modals allow-forms
310
  allow-scripts allow-same-origin allow-popups
311
  allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
312
  allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
313
 
314
+ def set_examples(example):
315
+ n,code, resids = example
316
+ return [
317
+ n,
318
+ code,
319
+ resids
320
+ ]
321
 
322
  metal3d = gr.Blocks()
323
 
 
340
  clustering_threshold = gr.Slider(minimum=0.15,maximum=1, value=0.15,step=0.05, label="Clustering threshold")
341
  distance_cutoff = gr.Slider(minimum=1,maximum=10, value=7,step=1, label="Clustering distance cutoff")
342
  btn = gr.Button("Run")
343
+ n = gr.Textbox(label="Label",visible=False)
344
+ examples = gr.Dataset(components=[n,inp, custom_resids],
345
+ samples=[["HCA2", "2CBA", ""],
346
+ ["Nickel in GB1 dimer", "6F5N", ""],
347
+ ["Zebrafish palmitoyltransferase ZDHHC15B PDB", "6BMS", ""],
348
+ ["Human palmitoyltransferase ZDHHC23 AlphaFold", "Q8IYP9", "280,273,263,260,274,277,274,287"]],
349
+ )
350
+ examples.click(fn=set_examples, inputs=examples, outputs=examples.components)
351
+ #gr.Markdown(
352
+ # """ <small>Inference using CPU-only, can be quite slow for more than 20 residues. Use Colab notebook for GPU acceleration</small>
353
+ #"""
354
+ #)
355
 
356
 
357
  gr.Markdown("# Output")
358
+
359
  out = gr.Textbox(label="status")
360
  mol = gr.HTML()
361
  btn.click(fn=update, inputs=[inp, file, mode, custom_resids, clustering_threshold], outputs=[out, mol])
362
 
363
+ metal3d.launch(share=True)
364
 
moleculekit-1.1.1.tar.gz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7751777ae97868b5194c6a0c5c9785867964c43befb8ea963db0642cf80a208d
3
- size 6434734
 
 
 
 
utils/voxelization.py CHANGED
@@ -177,7 +177,7 @@ def processStructures(pdb_file, resids, clean=True):
177
 
178
  # load molecule using MoleculeKit
179
  try:
180
- prot = Molecule('files/2CBA.pdb')
181
  except:
182
  raise IOError("could not read pdbfile")
183
 
@@ -196,8 +196,8 @@ def processStructures(pdb_file, resids, clean=True):
196
  envs = []
197
 
198
  results = [voxelize_single_notcentered(x) for x in environments]
199
-
200
- voxels = torch.empty(len(results), 8, 32, 32, 32, device="cpu")
201
 
202
  vox_env, prot_centers_list, prot_n_list, envs = zip(*results)
203
 
 
177
 
178
  # load molecule using MoleculeKit
179
  try:
180
+ prot = Molecule(pdb_file)
181
  except:
182
  raise IOError("could not read pdbfile")
183
 
 
196
  envs = []
197
 
198
  results = [voxelize_single_notcentered(x) for x in environments]
199
+ device = "cuda" if torch.cuda.is_available() else "cpu"
200
+ voxels = torch.empty(len(results), 8, 32, 32, 32, device=device)
201
 
202
  vox_env, prot_centers_list, prot_n_list, envs = zip(*results)
203