Spaces:
Running
Running
simonduerr
commited on
Commit
•
514575e
1
Parent(s):
40b62b9
Upload folder using huggingface_hub
Browse files- .gitignore +12 -0
- README.md +420 -10
- app.py +4 -12
- requirements.txt +1 -1
- space.py +9 -20
- src/.gitignore +3 -1
- src/README.md +53 -27
- src/backend/gradio_molecule3d/molecule3d.py +90 -47
- src/backend/gradio_molecule3d/templates/component/index.js +0 -0
- src/backend/gradio_molecule3d/templates/component/style.css +0 -0
- src/backend/gradio_molecule3d/templates/example/index.js +63 -48
- src/demo/app.py +4 -12
- src/demo/requirements.txt +1 -0
- src/demo/space.py +9 -20
- src/frontend/Example.svelte +2 -2
- src/frontend/Index.svelte +28 -97
- src/frontend/gradio.config.js +11 -0
- src/frontend/package-lock.json +0 -0
- src/frontend/package.json +22 -11
- src/frontend/shared/File.svelte +3 -5
- src/frontend/shared/FilePreview.svelte +113 -26
- src/frontend/shared/FileRetrieval.svelte +6 -3
- src/frontend/shared/FileUpload.svelte +25 -27
- src/frontend/shared/MolecularViewer.svelte +8 -17
- src/frontend/shared/utils.ts +0 -29
- src/frontend/style.css +1 -0
- src/pyproject.toml +7 -7
.gitignore
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.eggs/
|
2 |
+
dist/
|
3 |
+
*.pyc
|
4 |
+
__pycache__/
|
5 |
+
*.py[cod]
|
6 |
+
*$py.class
|
7 |
+
__tmp/*
|
8 |
+
*.pyi
|
9 |
+
.mypycache
|
10 |
+
.ruff_cache
|
11 |
+
node_modules
|
12 |
+
backend/**/templates/
|
README.md
CHANGED
@@ -1,17 +1,427 @@
|
|
1 |
-
|
2 |
---
|
3 |
-
tags: [gradio-custom-component,
|
4 |
-
title: gradio_molecule3d
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
8 |
pinned: false
|
9 |
-
|
10 |
---
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
-
|
14 |
|
15 |
-
|
|
|
16 |
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
tags: [gradio-custom-component, File]
|
3 |
+
title: gradio_molecule3d
|
4 |
+
short_description: A gradio custom component
|
5 |
+
colorFrom: blue
|
6 |
+
colorTo: yellow
|
7 |
+
sdk: gradio
|
8 |
pinned: false
|
9 |
+
app_file: space.py
|
10 |
---
|
11 |
|
12 |
+
# `gradio_molecule3d`
|
13 |
+
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
14 |
+
|
15 |
+
Python library for easily interacting with trained machine learning models
|
16 |
+
|
17 |
+
## Installation
|
18 |
+
|
19 |
+
```bash
|
20 |
+
pip install gradio_molecule3d
|
21 |
+
```
|
22 |
+
|
23 |
+
## Usage
|
24 |
+
|
25 |
+
```python
|
26 |
+
|
27 |
+
import gradio as gr
|
28 |
+
from gradio_molecule3d import Molecule3D
|
29 |
+
|
30 |
+
|
31 |
+
example = Molecule3D().example_value()
|
32 |
+
|
33 |
+
|
34 |
+
reps = [
|
35 |
+
{
|
36 |
+
"model": 0,
|
37 |
+
"chain": "",
|
38 |
+
"resname": "",
|
39 |
+
"style": "stick",
|
40 |
+
"color": "whiteCarbon",
|
41 |
+
"residue_range": "",
|
42 |
+
"around": 0,
|
43 |
+
"byres": False,
|
44 |
+
"visible": False
|
45 |
+
}
|
46 |
+
]
|
47 |
+
|
48 |
+
|
49 |
+
|
50 |
+
def predict(x):
|
51 |
+
print("predict function", x)
|
52 |
+
print(x.name)
|
53 |
+
return x
|
54 |
+
|
55 |
+
with gr.Blocks() as demo:
|
56 |
+
gr.Markdown("# Molecule3D")
|
57 |
+
inp = Molecule3D(label="Molecule3D", reps=reps)
|
58 |
+
out = Molecule3D(label="Output", reps=reps)
|
59 |
+
|
60 |
+
btn = gr.Button("Predict")
|
61 |
+
gr.Markdown("""
|
62 |
+
You can configure the default rendering of the molecule by adding a list of representations
|
63 |
+
<pre>
|
64 |
+
reps = [
|
65 |
+
{
|
66 |
+
"model": 0,
|
67 |
+
"style": "cartoon",
|
68 |
+
"color": "whiteCarbon",
|
69 |
+
"residue_range": "",
|
70 |
+
"around": 0,
|
71 |
+
"byres": False,
|
72 |
+
},
|
73 |
+
{
|
74 |
+
"model": 0,
|
75 |
+
"chain": "A",
|
76 |
+
"resname": "HIS",
|
77 |
+
"style": "stick",
|
78 |
+
"color": "red"
|
79 |
+
}
|
80 |
+
]
|
81 |
+
</pre>
|
82 |
+
""")
|
83 |
+
btn.click(predict, inputs=inp, outputs=out)
|
84 |
+
|
85 |
+
|
86 |
+
if __name__ == "__main__":
|
87 |
+
demo.launch()
|
88 |
+
|
89 |
+
```
|
90 |
+
|
91 |
+
## `Molecule3D`
|
92 |
+
|
93 |
+
### Initialization
|
94 |
+
|
95 |
+
<table>
|
96 |
+
<thead>
|
97 |
+
<tr>
|
98 |
+
<th align="left">name</th>
|
99 |
+
<th align="left" style="width: 25%;">type</th>
|
100 |
+
<th align="left">default</th>
|
101 |
+
<th align="left">description</th>
|
102 |
+
</tr>
|
103 |
+
</thead>
|
104 |
+
<tbody>
|
105 |
+
<tr>
|
106 |
+
<td align="left"><code>value</code></td>
|
107 |
+
<td align="left" style="width: 25%;">
|
108 |
+
|
109 |
+
```python
|
110 |
+
str | list[str] | Callable | None
|
111 |
+
```
|
112 |
+
|
113 |
+
</td>
|
114 |
+
<td align="left"><code>None</code></td>
|
115 |
+
<td align="left">Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.</td>
|
116 |
+
</tr>
|
117 |
+
|
118 |
+
<tr>
|
119 |
+
<td align="left"><code>reps</code></td>
|
120 |
+
<td align="left" style="width: 25%;">
|
121 |
+
|
122 |
+
```python
|
123 |
+
Any | None
|
124 |
+
```
|
125 |
+
|
126 |
+
</td>
|
127 |
+
<td align="left"><code>[]</code></td>
|
128 |
+
<td align="left">None</td>
|
129 |
+
</tr>
|
130 |
+
|
131 |
+
<tr>
|
132 |
+
<td align="left"><code>config</code></td>
|
133 |
+
<td align="left" style="width: 25%;">
|
134 |
+
|
135 |
+
```python
|
136 |
+
Any | None
|
137 |
+
```
|
138 |
+
|
139 |
+
</td>
|
140 |
+
<td align="left"><code>{
|
141 |
+
"backgroundColor": "white",
|
142 |
+
"orthographic": False,
|
143 |
+
"disableFog": False,
|
144 |
+
}</code></td>
|
145 |
+
<td align="left">dictionary of config options</td>
|
146 |
+
</tr>
|
147 |
+
|
148 |
+
<tr>
|
149 |
+
<td align="left"><code>confidenceLabel</code></td>
|
150 |
+
<td align="left" style="width: 25%;">
|
151 |
+
|
152 |
+
```python
|
153 |
+
str | None
|
154 |
+
```
|
155 |
+
|
156 |
+
</td>
|
157 |
+
<td align="left"><code>"pLDDT"</code></td>
|
158 |
+
<td align="left">label for confidence values stored in the bfactor column of a pdb file</td>
|
159 |
+
</tr>
|
160 |
+
|
161 |
+
<tr>
|
162 |
+
<td align="left"><code>file_count</code></td>
|
163 |
+
<td align="left" style="width: 25%;">
|
164 |
+
|
165 |
+
```python
|
166 |
+
Literal["single", "multiple", "directory"]
|
167 |
+
```
|
168 |
+
|
169 |
+
</td>
|
170 |
+
<td align="left"><code>"single"</code></td>
|
171 |
+
<td align="left">if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".</td>
|
172 |
+
</tr>
|
173 |
+
|
174 |
+
<tr>
|
175 |
+
<td align="left"><code>file_types</code></td>
|
176 |
+
<td align="left" style="width: 25%;">
|
177 |
+
|
178 |
+
```python
|
179 |
+
list[str] | None
|
180 |
+
```
|
181 |
+
|
182 |
+
</td>
|
183 |
+
<td align="left"><code>None</code></td>
|
184 |
+
<td align="left">List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.</td>
|
185 |
+
</tr>
|
186 |
+
|
187 |
+
<tr>
|
188 |
+
<td align="left"><code>type</code></td>
|
189 |
+
<td align="left" style="width: 25%;">
|
190 |
+
|
191 |
+
```python
|
192 |
+
Literal["filepath", "binary"]
|
193 |
+
```
|
194 |
+
|
195 |
+
</td>
|
196 |
+
<td align="left"><code>"filepath"</code></td>
|
197 |
+
<td align="left">Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.</td>
|
198 |
+
</tr>
|
199 |
+
|
200 |
+
<tr>
|
201 |
+
<td align="left"><code>label</code></td>
|
202 |
+
<td align="left" style="width: 25%;">
|
203 |
+
|
204 |
+
```python
|
205 |
+
str | None
|
206 |
+
```
|
207 |
+
|
208 |
+
</td>
|
209 |
+
<td align="left"><code>None</code></td>
|
210 |
+
<td align="left">The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.</td>
|
211 |
+
</tr>
|
212 |
+
|
213 |
+
<tr>
|
214 |
+
<td align="left"><code>every</code></td>
|
215 |
+
<td align="left" style="width: 25%;">
|
216 |
+
|
217 |
+
```python
|
218 |
+
Timer | float | None
|
219 |
+
```
|
220 |
+
|
221 |
+
</td>
|
222 |
+
<td align="left"><code>None</code></td>
|
223 |
+
<td align="left">Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.</td>
|
224 |
+
</tr>
|
225 |
+
|
226 |
+
<tr>
|
227 |
+
<td align="left"><code>inputs</code></td>
|
228 |
+
<td align="left" style="width: 25%;">
|
229 |
+
|
230 |
+
```python
|
231 |
+
Component | Sequence[Component] | set[Component] | None
|
232 |
+
```
|
233 |
+
|
234 |
+
</td>
|
235 |
+
<td align="left"><code>None</code></td>
|
236 |
+
<td align="left">Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.</td>
|
237 |
+
</tr>
|
238 |
+
|
239 |
+
<tr>
|
240 |
+
<td align="left"><code>show_label</code></td>
|
241 |
+
<td align="left" style="width: 25%;">
|
242 |
+
|
243 |
+
```python
|
244 |
+
bool | None
|
245 |
+
```
|
246 |
+
|
247 |
+
</td>
|
248 |
+
<td align="left"><code>None</code></td>
|
249 |
+
<td align="left">if True, will display label.</td>
|
250 |
+
</tr>
|
251 |
+
|
252 |
+
<tr>
|
253 |
+
<td align="left"><code>container</code></td>
|
254 |
+
<td align="left" style="width: 25%;">
|
255 |
+
|
256 |
+
```python
|
257 |
+
bool
|
258 |
+
```
|
259 |
+
|
260 |
+
</td>
|
261 |
+
<td align="left"><code>True</code></td>
|
262 |
+
<td align="left">If True, will place the component in a container - providing some extra padding around the border.</td>
|
263 |
+
</tr>
|
264 |
+
|
265 |
+
<tr>
|
266 |
+
<td align="left"><code>scale</code></td>
|
267 |
+
<td align="left" style="width: 25%;">
|
268 |
+
|
269 |
+
```python
|
270 |
+
int | None
|
271 |
+
```
|
272 |
+
|
273 |
+
</td>
|
274 |
+
<td align="left"><code>None</code></td>
|
275 |
+
<td align="left">relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.</td>
|
276 |
+
</tr>
|
277 |
+
|
278 |
+
<tr>
|
279 |
+
<td align="left"><code>min_width</code></td>
|
280 |
+
<td align="left" style="width: 25%;">
|
281 |
+
|
282 |
+
```python
|
283 |
+
int
|
284 |
+
```
|
285 |
+
|
286 |
+
</td>
|
287 |
+
<td align="left"><code>160</code></td>
|
288 |
+
<td align="left">minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.</td>
|
289 |
+
</tr>
|
290 |
+
|
291 |
+
<tr>
|
292 |
+
<td align="left"><code>height</code></td>
|
293 |
+
<td align="left" style="width: 25%;">
|
294 |
+
|
295 |
+
```python
|
296 |
+
int | float | None
|
297 |
+
```
|
298 |
+
|
299 |
+
</td>
|
300 |
+
<td align="left"><code>None</code></td>
|
301 |
+
<td align="left">The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.</td>
|
302 |
+
</tr>
|
303 |
+
|
304 |
+
<tr>
|
305 |
+
<td align="left"><code>interactive</code></td>
|
306 |
+
<td align="left" style="width: 25%;">
|
307 |
+
|
308 |
+
```python
|
309 |
+
bool | None
|
310 |
+
```
|
311 |
+
|
312 |
+
</td>
|
313 |
+
<td align="left"><code>None</code></td>
|
314 |
+
<td align="left">if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.</td>
|
315 |
+
</tr>
|
316 |
+
|
317 |
+
<tr>
|
318 |
+
<td align="left"><code>visible</code></td>
|
319 |
+
<td align="left" style="width: 25%;">
|
320 |
+
|
321 |
+
```python
|
322 |
+
bool
|
323 |
+
```
|
324 |
+
|
325 |
+
</td>
|
326 |
+
<td align="left"><code>True</code></td>
|
327 |
+
<td align="left">If False, component will be hidden.</td>
|
328 |
+
</tr>
|
329 |
+
|
330 |
+
<tr>
|
331 |
+
<td align="left"><code>elem_id</code></td>
|
332 |
+
<td align="left" style="width: 25%;">
|
333 |
+
|
334 |
+
```python
|
335 |
+
str | None
|
336 |
+
```
|
337 |
+
|
338 |
+
</td>
|
339 |
+
<td align="left"><code>None</code></td>
|
340 |
+
<td align="left">An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.</td>
|
341 |
+
</tr>
|
342 |
+
|
343 |
+
<tr>
|
344 |
+
<td align="left"><code>elem_classes</code></td>
|
345 |
+
<td align="left" style="width: 25%;">
|
346 |
+
|
347 |
+
```python
|
348 |
+
list[str] | str | None
|
349 |
+
```
|
350 |
+
|
351 |
+
</td>
|
352 |
+
<td align="left"><code>None</code></td>
|
353 |
+
<td align="left">An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.</td>
|
354 |
+
</tr>
|
355 |
+
|
356 |
+
<tr>
|
357 |
+
<td align="left"><code>render</code></td>
|
358 |
+
<td align="left" style="width: 25%;">
|
359 |
+
|
360 |
+
```python
|
361 |
+
bool
|
362 |
+
```
|
363 |
+
|
364 |
+
</td>
|
365 |
+
<td align="left"><code>True</code></td>
|
366 |
+
<td align="left">If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.</td>
|
367 |
+
</tr>
|
368 |
+
|
369 |
+
<tr>
|
370 |
+
<td align="left"><code>key</code></td>
|
371 |
+
<td align="left" style="width: 25%;">
|
372 |
+
|
373 |
+
```python
|
374 |
+
int | str | None
|
375 |
+
```
|
376 |
+
|
377 |
+
</td>
|
378 |
+
<td align="left"><code>None</code></td>
|
379 |
+
<td align="left">if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.</td>
|
380 |
+
</tr>
|
381 |
+
|
382 |
+
<tr>
|
383 |
+
<td align="left"><code>showviewer</code></td>
|
384 |
+
<td align="left" style="width: 25%;">
|
385 |
+
|
386 |
+
```python
|
387 |
+
bool
|
388 |
+
```
|
389 |
+
|
390 |
+
</td>
|
391 |
+
<td align="left"><code>True</code></td>
|
392 |
+
<td align="left">If True, will display the 3Dmol.js viewer. If False, will not display the 3Dmol.js viewer.</td>
|
393 |
+
</tr>
|
394 |
+
</tbody></table>
|
395 |
+
|
396 |
+
|
397 |
+
### Events
|
398 |
+
|
399 |
+
| name | description |
|
400 |
+
|:-----|:------------|
|
401 |
+
| `change` | Triggered when the value of the Molecule3D changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input. |
|
402 |
+
| `select` | Event listener for when the user selects or deselects the Molecule3D. Uses event data gradio.SelectData to carry `value` referring to the label of the Molecule3D, and `selected` to refer to state of the Molecule3D. See EventData documentation on how to use this event data |
|
403 |
+
| `clear` | This listener is triggered when the user clears the Molecule3D using the clear button for the component. |
|
404 |
+
| `upload` | This listener is triggered when the user uploads a file into the Molecule3D. |
|
405 |
+
| `delete` | This listener is triggered when the user deletes and item from the Molecule3D. Uses event data gradio.DeletedFileData to carry `value` referring to the file that was deleted as an instance of FileData. See EventData documentation on how to use this event data |
|
406 |
+
|
407 |
+
|
408 |
+
|
409 |
+
### User function
|
410 |
+
|
411 |
+
The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
|
412 |
+
|
413 |
+
- When used as an Input, the component only impacts the input signature of the user function.
|
414 |
+
- When used as an output, the component only impacts the return signature of the user function.
|
415 |
|
416 |
+
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
417 |
|
418 |
+
- **As output:** Is passed, passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.
|
419 |
+
- **As input:** Should return, expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
|
420 |
|
421 |
+
```python
|
422 |
+
def predict(
|
423 |
+
value: bytes | str | list[bytes] | list[str] | None
|
424 |
+
) -> str | list[str] | None:
|
425 |
+
return value
|
426 |
+
```
|
427 |
+
|
app.py
CHANGED
@@ -2,9 +2,8 @@
|
|
2 |
import gradio as gr
|
3 |
from gradio_molecule3d import Molecule3D
|
4 |
|
5 |
-
import os
|
6 |
|
7 |
-
example = Molecule3D().
|
8 |
|
9 |
|
10 |
reps = [
|
@@ -40,25 +39,18 @@ with gr.Blocks() as demo:
|
|
40 |
reps = [
|
41 |
{
|
42 |
"model": 0,
|
43 |
-
"chain": "",
|
44 |
-
"resname": "",
|
45 |
"style": "cartoon",
|
46 |
"color": "whiteCarbon",
|
47 |
"residue_range": "",
|
48 |
"around": 0,
|
49 |
"byres": False,
|
50 |
-
"visible": False,
|
51 |
},
|
52 |
{
|
53 |
"model": 0,
|
54 |
"chain": "A",
|
55 |
"resname": "HIS",
|
56 |
"style": "stick",
|
57 |
-
"color": "red"
|
58 |
-
"residue_range": "",
|
59 |
-
"around": 0,
|
60 |
-
"byres": False,
|
61 |
-
"visible": False,
|
62 |
}
|
63 |
]
|
64 |
</pre>
|
@@ -66,5 +58,5 @@ with gr.Blocks() as demo:
|
|
66 |
btn.click(predict, inputs=inp, outputs=out)
|
67 |
|
68 |
|
69 |
-
if __name__ ==
|
70 |
-
|
|
|
2 |
import gradio as gr
|
3 |
from gradio_molecule3d import Molecule3D
|
4 |
|
|
|
5 |
|
6 |
+
example = Molecule3D().example_value()
|
7 |
|
8 |
|
9 |
reps = [
|
|
|
39 |
reps = [
|
40 |
{
|
41 |
"model": 0,
|
|
|
|
|
42 |
"style": "cartoon",
|
43 |
"color": "whiteCarbon",
|
44 |
"residue_range": "",
|
45 |
"around": 0,
|
46 |
"byres": False,
|
|
|
47 |
},
|
48 |
{
|
49 |
"model": 0,
|
50 |
"chain": "A",
|
51 |
"resname": "HIS",
|
52 |
"style": "stick",
|
53 |
+
"color": "red"
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
]
|
56 |
</pre>
|
|
|
58 |
btn.click(predict, inputs=inp, outputs=out)
|
59 |
|
60 |
|
61 |
+
if __name__ == "__main__":
|
62 |
+
demo.launch()
|
requirements.txt
CHANGED
@@ -1 +1 @@
|
|
1 |
-
gradio_molecule3d
|
|
|
1 |
+
gradio_molecule3d
|
space.py
CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
-
_docs = {'Molecule3D': {'description': 'Creates a file component that allows uploading generic
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -24,7 +24,7 @@ with gr.Blocks(
|
|
24 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
25 |
</div>
|
26 |
|
27 |
-
|
28 |
""", elem_classes=["md-custom"], header_links=True)
|
29 |
app.render()
|
30 |
gr.Markdown(
|
@@ -42,9 +42,8 @@ pip install gradio_molecule3d
|
|
42 |
import gradio as gr
|
43 |
from gradio_molecule3d import Molecule3D
|
44 |
|
45 |
-
import os
|
46 |
|
47 |
-
example = Molecule3D().
|
48 |
|
49 |
|
50 |
reps = [
|
@@ -80,25 +79,18 @@ with gr.Blocks() as demo:
|
|
80 |
reps = [
|
81 |
{
|
82 |
"model": 0,
|
83 |
-
"chain": "",
|
84 |
-
"resname": "",
|
85 |
"style": "cartoon",
|
86 |
"color": "whiteCarbon",
|
87 |
"residue_range": "",
|
88 |
"around": 0,
|
89 |
"byres": False,
|
90 |
-
"visible": False,
|
91 |
},
|
92 |
{
|
93 |
"model": 0,
|
94 |
"chain": "A",
|
95 |
"resname": "HIS",
|
96 |
"style": "stick",
|
97 |
-
"color": "red"
|
98 |
-
"residue_range": "",
|
99 |
-
"around": 0,
|
100 |
-
"byres": False,
|
101 |
-
"visible": False,
|
102 |
}
|
103 |
]
|
104 |
</pre>
|
@@ -106,8 +98,8 @@ with gr.Blocks() as demo:
|
|
106 |
btn.click(predict, inputs=inp, outputs=out)
|
107 |
|
108 |
|
109 |
-
if __name__ ==
|
110 |
-
|
111 |
|
112 |
```
|
113 |
""", elem_classes=["md-custom"], header_links=True)
|
@@ -139,15 +131,12 @@ The impact on the users predict function varies depending on whether the compone
|
|
139 |
|
140 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
141 |
|
142 |
-
- **As input:** Is passed, the
|
143 |
-
- **As output:** Should return,
|
144 |
|
145 |
```python
|
146 |
def predict(
|
147 |
-
value: bytes
|
148 |
-
| gradio.utils.NamedString
|
149 |
-
| list[bytes | gradio.utils.NamedString]
|
150 |
-
| None
|
151 |
) -> str | list[str] | None:
|
152 |
return value
|
153 |
```
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'Molecule3D': {'description': 'Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output).\n', 'members': {'__init__': {'value': {'type': 'str | list[str] | Callable | None', 'default': 'None', 'description': 'Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.'}, 'reps': {'type': 'Any | None', 'default': '[]', 'description': None}, 'config': {'type': 'Any | None', 'default': '{\n "backgroundColor": "white",\n "orthographic": False,\n "disableFog": False,\n}', 'description': 'dictionary of config options'}, 'confidenceLabel': {'type': 'str | None', 'default': '"pLDDT"', 'description': 'label for confidence values stored in the bfactor column of a pdb file'}, 'file_count': {'type': 'Literal["single", "multiple", "directory"]', 'default': '"single"', 'description': 'if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".'}, 'file_types': {'type': 'list[str] | None', 'default': 'None', 'description': 'List of file extensions or types of files to be uploaded (e.g. [\'image\', \'.json\', \'.mp4\']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.'}, 'type': {'type': 'Literal["filepath", "binary"]', 'default': '"filepath"', 'description': 'Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.'}, 'every': {'type': 'Timer | float | None', 'default': 'None', 'description': 'Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.'}, 'inputs': {'type': 'Component | Sequence[Component] | set[Component] | None', 'default': 'None', 'description': 'Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.'}, 'show_label': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will display label.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, will place the component in a container - providing some extra padding around the border.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.'}, 'min_width': {'type': 'int', 'default': '160', 'description': 'minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.'}, 'height': {'type': 'int | float | None', 'default': 'None', 'description': 'The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.'}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, component will be hidden.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.'}, 'render': {'type': 'bool', 'default': 'True', 'description': 'If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.'}, 'key': {'type': 'int | str | None', 'default': 'None', 'description': 'if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.'}, 'showviewer': {'type': 'bool', 'default': 'True', 'description': 'If True, will display the 3Dmol.js viewer. If False, will not display the 3Dmol.js viewer.'}}, 'postprocess': {'value': {'type': 'str | list[str] | None', 'description': 'Expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.'}}, 'preprocess': {'return': {'type': 'bytes | str | list[bytes] | list[str] | None', 'description': 'Passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the Molecule3D changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'select': {'type': None, 'default': None, 'description': 'Event listener for when the user selects or deselects the Molecule3D. Uses event data gradio.SelectData to carry `value` referring to the label of the Molecule3D, and `selected` to refer to state of the Molecule3D. See EventData documentation on how to use this event data'}, 'clear': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clears the Molecule3D using the clear button for the component.'}, 'upload': {'type': None, 'default': None, 'description': 'This listener is triggered when the user uploads a file into the Molecule3D.'}, 'delete': {'type': None, 'default': None, 'description': 'This listener is triggered when the user deletes and item from the Molecule3D. Uses event data gradio.DeletedFileData to carry `value` referring to the file that was deleted as an instance of FileData. See EventData documentation on how to use this event data'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'Molecule3D': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
24 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
25 |
</div>
|
26 |
|
27 |
+
Python library for easily interacting with trained machine learning models
|
28 |
""", elem_classes=["md-custom"], header_links=True)
|
29 |
app.render()
|
30 |
gr.Markdown(
|
|
|
42 |
import gradio as gr
|
43 |
from gradio_molecule3d import Molecule3D
|
44 |
|
|
|
45 |
|
46 |
+
example = Molecule3D().example_value()
|
47 |
|
48 |
|
49 |
reps = [
|
|
|
79 |
reps = [
|
80 |
{
|
81 |
"model": 0,
|
|
|
|
|
82 |
"style": "cartoon",
|
83 |
"color": "whiteCarbon",
|
84 |
"residue_range": "",
|
85 |
"around": 0,
|
86 |
"byres": False,
|
|
|
87 |
},
|
88 |
{
|
89 |
"model": 0,
|
90 |
"chain": "A",
|
91 |
"resname": "HIS",
|
92 |
"style": "stick",
|
93 |
+
"color": "red"
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
]
|
96 |
</pre>
|
|
|
98 |
btn.click(predict, inputs=inp, outputs=out)
|
99 |
|
100 |
|
101 |
+
if __name__ == "__main__":
|
102 |
+
demo.launch()
|
103 |
|
104 |
```
|
105 |
""", elem_classes=["md-custom"], header_links=True)
|
|
|
131 |
|
132 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
133 |
|
134 |
+
- **As input:** Is passed, passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.
|
135 |
+
- **As output:** Should return, expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
|
136 |
|
137 |
```python
|
138 |
def predict(
|
139 |
+
value: bytes | str | list[bytes] | list[str] | None
|
|
|
|
|
|
|
140 |
) -> str | list[str] | None:
|
141 |
return value
|
142 |
```
|
src/.gitignore
CHANGED
@@ -6,5 +6,7 @@ __pycache__/
|
|
6 |
*$py.class
|
7 |
__tmp/*
|
8 |
*.pyi
|
|
|
|
|
9 |
node_modules
|
10 |
-
|
|
|
6 |
*$py.class
|
7 |
__tmp/*
|
8 |
*.pyi
|
9 |
+
.mypycache
|
10 |
+
.ruff_cache
|
11 |
node_modules
|
12 |
+
backend/**/templates/
|
src/README.md
CHANGED
@@ -1,8 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
# `gradio_molecule3d`
|
3 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
4 |
|
5 |
-
|
6 |
|
7 |
## Installation
|
8 |
|
@@ -17,9 +27,8 @@ pip install gradio_molecule3d
|
|
17 |
import gradio as gr
|
18 |
from gradio_molecule3d import Molecule3D
|
19 |
|
20 |
-
import os
|
21 |
|
22 |
-
example = Molecule3D().
|
23 |
|
24 |
|
25 |
reps = [
|
@@ -55,25 +64,18 @@ with gr.Blocks() as demo:
|
|
55 |
reps = [
|
56 |
{
|
57 |
"model": 0,
|
58 |
-
"chain": "",
|
59 |
-
"resname": "",
|
60 |
"style": "cartoon",
|
61 |
"color": "whiteCarbon",
|
62 |
"residue_range": "",
|
63 |
"around": 0,
|
64 |
"byres": False,
|
65 |
-
"visible": False,
|
66 |
},
|
67 |
{
|
68 |
"model": 0,
|
69 |
"chain": "A",
|
70 |
"resname": "HIS",
|
71 |
"style": "stick",
|
72 |
-
"color": "red"
|
73 |
-
"residue_range": "",
|
74 |
-
"around": 0,
|
75 |
-
"byres": False,
|
76 |
-
"visible": False,
|
77 |
}
|
78 |
]
|
79 |
</pre>
|
@@ -81,8 +83,8 @@ with gr.Blocks() as demo:
|
|
81 |
btn.click(predict, inputs=inp, outputs=out)
|
82 |
|
83 |
|
84 |
-
if __name__ ==
|
85 |
-
|
86 |
|
87 |
```
|
88 |
|
@@ -110,7 +112,7 @@ str | list[str] | Callable | None
|
|
110 |
|
111 |
</td>
|
112 |
<td align="left"><code>None</code></td>
|
113 |
-
<td align="left">Default file to display, given as str file path. If callable, the function will be called whenever the app loads to set the initial value of the component.</td>
|
114 |
</tr>
|
115 |
|
116 |
<tr>
|
@@ -161,7 +163,7 @@ str | None
|
|
161 |
<td align="left" style="width: 25%;">
|
162 |
|
163 |
```python
|
164 |
-
"single"
|
165 |
```
|
166 |
|
167 |
</td>
|
@@ -187,7 +189,7 @@ list[str] | None
|
|
187 |
<td align="left" style="width: 25%;">
|
188 |
|
189 |
```python
|
190 |
-
"filepath"
|
191 |
```
|
192 |
|
193 |
</td>
|
@@ -213,12 +215,25 @@ str | None
|
|
213 |
<td align="left" style="width: 25%;">
|
214 |
|
215 |
```python
|
216 |
-
float | None
|
217 |
```
|
218 |
|
219 |
</td>
|
220 |
<td align="left"><code>None</code></td>
|
221 |
-
<td align="left">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
</tr>
|
223 |
|
224 |
<tr>
|
@@ -257,7 +272,7 @@ int | None
|
|
257 |
|
258 |
</td>
|
259 |
<td align="left"><code>None</code></td>
|
260 |
-
<td align="left">relative
|
261 |
</tr>
|
262 |
|
263 |
<tr>
|
@@ -283,7 +298,7 @@ int | float | None
|
|
283 |
|
284 |
</td>
|
285 |
<td align="left"><code>None</code></td>
|
286 |
-
<td align="left">The maximum height of the file component, in pixels. If more files are uploaded than can fit in the height, a scrollbar will appear.</td>
|
287 |
</tr>
|
288 |
|
289 |
<tr>
|
@@ -351,6 +366,19 @@ bool
|
|
351 |
<td align="left">If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.</td>
|
352 |
</tr>
|
353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
<tr>
|
355 |
<td align="left"><code>showviewer</code></td>
|
356 |
<td align="left" style="width: 25%;">
|
@@ -372,8 +400,9 @@ bool
|
|
372 |
|:-----|:------------|
|
373 |
| `change` | Triggered when the value of the Molecule3D changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input. |
|
374 |
| `select` | Event listener for when the user selects or deselects the Molecule3D. Uses event data gradio.SelectData to carry `value` referring to the label of the Molecule3D, and `selected` to refer to state of the Molecule3D. See EventData documentation on how to use this event data |
|
375 |
-
| `clear` | This listener is triggered when the user clears the Molecule3D using the
|
376 |
| `upload` | This listener is triggered when the user uploads a file into the Molecule3D. |
|
|
|
377 |
|
378 |
|
379 |
|
@@ -386,15 +415,12 @@ The impact on the users predict function varies depending on whether the compone
|
|
386 |
|
387 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
388 |
|
389 |
-
- **As output:** Is passed, the
|
390 |
-
- **As input:** Should return,
|
391 |
|
392 |
```python
|
393 |
def predict(
|
394 |
-
value: bytes
|
395 |
-
| gradio.utils.NamedString
|
396 |
-
| list[bytes | gradio.utils.NamedString]
|
397 |
-
| None
|
398 |
) -> str | list[str] | None:
|
399 |
return value
|
400 |
```
|
|
|
1 |
+
---
|
2 |
+
tags: [gradio-custom-component, File]
|
3 |
+
title: gradio_molecule3d
|
4 |
+
short_description: A gradio custom component
|
5 |
+
colorFrom: blue
|
6 |
+
colorTo: yellow
|
7 |
+
sdk: gradio
|
8 |
+
pinned: false
|
9 |
+
app_file: space.py
|
10 |
+
---
|
11 |
|
12 |
# `gradio_molecule3d`
|
13 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
14 |
|
15 |
+
Python library for easily interacting with trained machine learning models
|
16 |
|
17 |
## Installation
|
18 |
|
|
|
27 |
import gradio as gr
|
28 |
from gradio_molecule3d import Molecule3D
|
29 |
|
|
|
30 |
|
31 |
+
example = Molecule3D().example_value()
|
32 |
|
33 |
|
34 |
reps = [
|
|
|
64 |
reps = [
|
65 |
{
|
66 |
"model": 0,
|
|
|
|
|
67 |
"style": "cartoon",
|
68 |
"color": "whiteCarbon",
|
69 |
"residue_range": "",
|
70 |
"around": 0,
|
71 |
"byres": False,
|
|
|
72 |
},
|
73 |
{
|
74 |
"model": 0,
|
75 |
"chain": "A",
|
76 |
"resname": "HIS",
|
77 |
"style": "stick",
|
78 |
+
"color": "red"
|
|
|
|
|
|
|
|
|
79 |
}
|
80 |
]
|
81 |
</pre>
|
|
|
83 |
btn.click(predict, inputs=inp, outputs=out)
|
84 |
|
85 |
|
86 |
+
if __name__ == "__main__":
|
87 |
+
demo.launch()
|
88 |
|
89 |
```
|
90 |
|
|
|
112 |
|
113 |
</td>
|
114 |
<td align="left"><code>None</code></td>
|
115 |
+
<td align="left">Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.</td>
|
116 |
</tr>
|
117 |
|
118 |
<tr>
|
|
|
163 |
<td align="left" style="width: 25%;">
|
164 |
|
165 |
```python
|
166 |
+
Literal["single", "multiple", "directory"]
|
167 |
```
|
168 |
|
169 |
</td>
|
|
|
189 |
<td align="left" style="width: 25%;">
|
190 |
|
191 |
```python
|
192 |
+
Literal["filepath", "binary"]
|
193 |
```
|
194 |
|
195 |
</td>
|
|
|
215 |
<td align="left" style="width: 25%;">
|
216 |
|
217 |
```python
|
218 |
+
Timer | float | None
|
219 |
```
|
220 |
|
221 |
</td>
|
222 |
<td align="left"><code>None</code></td>
|
223 |
+
<td align="left">Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.</td>
|
224 |
+
</tr>
|
225 |
+
|
226 |
+
<tr>
|
227 |
+
<td align="left"><code>inputs</code></td>
|
228 |
+
<td align="left" style="width: 25%;">
|
229 |
+
|
230 |
+
```python
|
231 |
+
Component | Sequence[Component] | set[Component] | None
|
232 |
+
```
|
233 |
+
|
234 |
+
</td>
|
235 |
+
<td align="left"><code>None</code></td>
|
236 |
+
<td align="left">Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.</td>
|
237 |
</tr>
|
238 |
|
239 |
<tr>
|
|
|
272 |
|
273 |
</td>
|
274 |
<td align="left"><code>None</code></td>
|
275 |
+
<td align="left">relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.</td>
|
276 |
</tr>
|
277 |
|
278 |
<tr>
|
|
|
298 |
|
299 |
</td>
|
300 |
<td align="left"><code>None</code></td>
|
301 |
+
<td align="left">The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.</td>
|
302 |
</tr>
|
303 |
|
304 |
<tr>
|
|
|
366 |
<td align="left">If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.</td>
|
367 |
</tr>
|
368 |
|
369 |
+
<tr>
|
370 |
+
<td align="left"><code>key</code></td>
|
371 |
+
<td align="left" style="width: 25%;">
|
372 |
+
|
373 |
+
```python
|
374 |
+
int | str | None
|
375 |
+
```
|
376 |
+
|
377 |
+
</td>
|
378 |
+
<td align="left"><code>None</code></td>
|
379 |
+
<td align="left">if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.</td>
|
380 |
+
</tr>
|
381 |
+
|
382 |
<tr>
|
383 |
<td align="left"><code>showviewer</code></td>
|
384 |
<td align="left" style="width: 25%;">
|
|
|
400 |
|:-----|:------------|
|
401 |
| `change` | Triggered when the value of the Molecule3D changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input. |
|
402 |
| `select` | Event listener for when the user selects or deselects the Molecule3D. Uses event data gradio.SelectData to carry `value` referring to the label of the Molecule3D, and `selected` to refer to state of the Molecule3D. See EventData documentation on how to use this event data |
|
403 |
+
| `clear` | This listener is triggered when the user clears the Molecule3D using the clear button for the component. |
|
404 |
| `upload` | This listener is triggered when the user uploads a file into the Molecule3D. |
|
405 |
+
| `delete` | This listener is triggered when the user deletes and item from the Molecule3D. Uses event data gradio.DeletedFileData to carry `value` referring to the file that was deleted as an instance of FileData. See EventData documentation on how to use this event data |
|
406 |
|
407 |
|
408 |
|
|
|
415 |
|
416 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
417 |
|
418 |
+
- **As output:** Is passed, passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.
|
419 |
+
- **As input:** Should return, expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
|
420 |
|
421 |
```python
|
422 |
def predict(
|
423 |
+
value: bytes | str | list[bytes] | list[str] | None
|
|
|
|
|
|
|
424 |
) -> str | list[str] | None:
|
425 |
return value
|
426 |
```
|
src/backend/gradio_molecule3d/molecule3d.py
CHANGED
@@ -5,44 +5,35 @@ from __future__ import annotations
|
|
5 |
import tempfile
|
6 |
import warnings
|
7 |
from pathlib import Path
|
8 |
-
from typing import Any, Callable,
|
9 |
|
10 |
-
|
|
|
|
|
11 |
|
|
|
12 |
from gradio.components.base import Component
|
13 |
-
from gradio.data_classes import FileData,
|
14 |
from gradio.events import Events
|
15 |
from gradio.utils import NamedString
|
16 |
|
17 |
-
|
|
|
18 |
|
19 |
|
20 |
-
class ListFiles(GradioRootModel):
|
21 |
-
root: List[FileData]
|
22 |
-
|
23 |
-
def __getitem__(self, index):
|
24 |
-
return self.root[index]
|
25 |
-
|
26 |
-
def __iter__(self):
|
27 |
-
return iter(self.root)
|
28 |
-
|
29 |
-
|
30 |
-
@document()
|
31 |
class Molecule3D(Component):
|
32 |
"""
|
33 |
-
Creates a file component that allows uploading generic
|
34 |
-
|
35 |
-
|
36 |
-
Examples-format: a {str} path to a local file that populates the component.
|
37 |
-
Demos: zip_to_json, zip_files
|
38 |
"""
|
39 |
|
40 |
-
EVENTS = [Events.change, Events.select, Events.clear, Events.upload]
|
41 |
|
42 |
def __init__(
|
43 |
self,
|
44 |
value: str | list[str] | Callable | None = None,
|
45 |
-
|
46 |
config: Any | None = {
|
47 |
"backgroundColor": "white",
|
48 |
"orthographic": False,
|
@@ -54,7 +45,8 @@ class Molecule3D(Component):
|
|
54 |
file_types: list[str] | None = None,
|
55 |
type: Literal["filepath", "binary"] = "filepath",
|
56 |
label: str | None = None,
|
57 |
-
every: float | None = None,
|
|
|
58 |
show_label: bool | None = None,
|
59 |
container: bool = True,
|
60 |
scale: int | None = None,
|
@@ -65,11 +57,12 @@ class Molecule3D(Component):
|
|
65 |
elem_id: str | None = None,
|
66 |
elem_classes: list[str] | str | None = None,
|
67 |
render: bool = True,
|
68 |
-
|
|
|
69 |
):
|
70 |
"""
|
71 |
Parameters:
|
72 |
-
value: Default file to display, given as str file path. If callable, the function will be called whenever the app loads to set the initial value of the component.
|
73 |
file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
|
74 |
file_types: List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
|
75 |
representations: list of representation objects
|
@@ -77,21 +70,29 @@ class Molecule3D(Component):
|
|
77 |
confidenceLabel: label for confidence values stored in the bfactor column of a pdb file
|
78 |
type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
|
79 |
label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
|
80 |
-
every:
|
|
|
81 |
show_label: if True, will display label.
|
82 |
container: If True, will place the component in a container - providing some extra padding around the border.
|
83 |
-
scale: relative
|
84 |
min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
|
85 |
-
height: The maximum height of the file component, in pixels. If more files are uploaded than can fit in the height, a scrollbar will appear.
|
86 |
interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
|
87 |
visible: If False, component will be hidden.
|
88 |
elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
|
89 |
elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
|
90 |
render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
|
|
|
91 |
showviewer: If True, will display the 3Dmol.js viewer. If False, will not display the 3Dmol.js viewer.
|
92 |
"""
|
|
|
93 |
self.file_count = file_count
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
95 |
self.data_model = ListFiles
|
96 |
else:
|
97 |
self.data_model = FileData
|
@@ -115,6 +116,7 @@ class Molecule3D(Component):
|
|
115 |
super().__init__(
|
116 |
label=label,
|
117 |
every=every,
|
|
|
118 |
show_label=show_label,
|
119 |
container=container,
|
120 |
scale=scale,
|
@@ -124,6 +126,7 @@ class Molecule3D(Component):
|
|
124 |
elem_id=elem_id,
|
125 |
elem_classes=elem_classes,
|
126 |
render=render,
|
|
|
127 |
value=value,
|
128 |
)
|
129 |
self.type = type
|
@@ -133,7 +136,6 @@ class Molecule3D(Component):
|
|
133 |
self.confidenceLabel = confidenceLabel
|
134 |
self.showviewer = showviewer
|
135 |
|
136 |
-
|
137 |
def _process_single_file(self, f: FileData) -> NamedString | bytes:
|
138 |
file_name = f.path
|
139 |
if self.type == "filepath":
|
@@ -152,25 +154,54 @@ class Molecule3D(Component):
|
|
152 |
|
153 |
def preprocess(
|
154 |
self, payload: ListFiles | FileData | None
|
155 |
-
) -> bytes |
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
if payload is None:
|
157 |
return None
|
|
|
158 |
if self.file_count == "single":
|
159 |
if isinstance(payload, ListFiles):
|
160 |
return self._process_single_file(payload[0])
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
else:
|
164 |
-
|
165 |
-
return [self._process_single_file(f) for f in payload]
|
166 |
-
else:
|
167 |
-
return [self._process_single_file(payload)]
|
168 |
|
169 |
def postprocess(self, value: str | list[str] | None) -> ListFiles | FileData | None:
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
if value is None:
|
171 |
return None
|
172 |
-
|
173 |
-
|
174 |
if isinstance(value, list):
|
175 |
return ListFiles(
|
176 |
root=[
|
@@ -189,18 +220,30 @@ class Molecule3D(Component):
|
|
189 |
size=Path(value).stat().st_size,
|
190 |
)
|
191 |
|
192 |
-
def
|
193 |
-
if
|
194 |
return ""
|
195 |
-
elif isinstance(
|
196 |
-
return ", ".join([Path(file).name for file in
|
197 |
else:
|
198 |
-
return Path(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
|
200 |
-
def
|
201 |
if self.file_count == "single":
|
202 |
-
return "/
|
203 |
else:
|
204 |
return [
|
205 |
-
"
|
206 |
]
|
|
|
5 |
import tempfile
|
6 |
import warnings
|
7 |
from pathlib import Path
|
8 |
+
from typing import TYPE_CHECKING, Any, Callable, Literal, Sequence
|
9 |
|
10 |
+
import gradio_client.utils as client_utils
|
11 |
+
from gradio_client import handle_file
|
12 |
+
from gradio_client.documentation import document
|
13 |
|
14 |
+
from gradio import processing_utils
|
15 |
from gradio.components.base import Component
|
16 |
+
from gradio.data_classes import FileData, ListFiles
|
17 |
from gradio.events import Events
|
18 |
from gradio.utils import NamedString
|
19 |
|
20 |
+
if TYPE_CHECKING:
|
21 |
+
from gradio.components import Timer
|
22 |
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
class Molecule3D(Component):
|
25 |
"""
|
26 |
+
Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output).
|
27 |
+
|
28 |
+
Demo: zip_files, zip_to_json
|
|
|
|
|
29 |
"""
|
30 |
|
31 |
+
EVENTS = [Events.change, Events.select, Events.clear, Events.upload, Events.delete]
|
32 |
|
33 |
def __init__(
|
34 |
self,
|
35 |
value: str | list[str] | Callable | None = None,
|
36 |
+
reps: Any | None = [],
|
37 |
config: Any | None = {
|
38 |
"backgroundColor": "white",
|
39 |
"orthographic": False,
|
|
|
45 |
file_types: list[str] | None = None,
|
46 |
type: Literal["filepath", "binary"] = "filepath",
|
47 |
label: str | None = None,
|
48 |
+
every: Timer | float | None = None,
|
49 |
+
inputs: Component | Sequence[Component] | set[Component] | None = None,
|
50 |
show_label: bool | None = None,
|
51 |
container: bool = True,
|
52 |
scale: int | None = None,
|
|
|
57 |
elem_id: str | None = None,
|
58 |
elem_classes: list[str] | str | None = None,
|
59 |
render: bool = True,
|
60 |
+
key: int | str | None = None,
|
61 |
+
showviewer: bool = True
|
62 |
):
|
63 |
"""
|
64 |
Parameters:
|
65 |
+
value: Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.
|
66 |
file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
|
67 |
file_types: List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
|
68 |
representations: list of representation objects
|
|
|
70 |
confidenceLabel: label for confidence values stored in the bfactor column of a pdb file
|
71 |
type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
|
72 |
label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
|
73 |
+
every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.
|
74 |
+
inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
|
75 |
show_label: if True, will display label.
|
76 |
container: If True, will place the component in a container - providing some extra padding around the border.
|
77 |
+
scale: relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.
|
78 |
min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
|
79 |
+
height: The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.
|
80 |
interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
|
81 |
visible: If False, component will be hidden.
|
82 |
elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
|
83 |
elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.
|
84 |
render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.
|
85 |
+
key: if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.
|
86 |
showviewer: If True, will display the 3Dmol.js viewer. If False, will not display the 3Dmol.js viewer.
|
87 |
"""
|
88 |
+
file_count_valid_types = ["single", "multiple", "directory"]
|
89 |
self.file_count = file_count
|
90 |
+
|
91 |
+
if self.file_count not in file_count_valid_types:
|
92 |
+
raise ValueError(
|
93 |
+
f"Parameter file_count must be one of them: {file_count_valid_types}"
|
94 |
+
)
|
95 |
+
elif self.file_count in ["multiple", "directory"]:
|
96 |
self.data_model = ListFiles
|
97 |
else:
|
98 |
self.data_model = FileData
|
|
|
116 |
super().__init__(
|
117 |
label=label,
|
118 |
every=every,
|
119 |
+
inputs=inputs,
|
120 |
show_label=show_label,
|
121 |
container=container,
|
122 |
scale=scale,
|
|
|
126 |
elem_id=elem_id,
|
127 |
elem_classes=elem_classes,
|
128 |
render=render,
|
129 |
+
key=key,
|
130 |
value=value,
|
131 |
)
|
132 |
self.type = type
|
|
|
136 |
self.confidenceLabel = confidenceLabel
|
137 |
self.showviewer = showviewer
|
138 |
|
|
|
139 |
def _process_single_file(self, f: FileData) -> NamedString | bytes:
|
140 |
file_name = f.path
|
141 |
if self.type == "filepath":
|
|
|
154 |
|
155 |
def preprocess(
|
156 |
self, payload: ListFiles | FileData | None
|
157 |
+
) -> bytes | str | list[bytes] | list[str] | None:
|
158 |
+
"""
|
159 |
+
Parameters:
|
160 |
+
payload: molecule3d information as a FileData object, or a list of FileData objects.
|
161 |
+
Returns:
|
162 |
+
Passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.
|
163 |
+
"""
|
164 |
if payload is None:
|
165 |
return None
|
166 |
+
|
167 |
if self.file_count == "single":
|
168 |
if isinstance(payload, ListFiles):
|
169 |
return self._process_single_file(payload[0])
|
170 |
+
return self._process_single_file(payload)
|
171 |
+
if isinstance(payload, ListFiles):
|
172 |
+
return [self._process_single_file(f) for f in payload] # type: ignore
|
173 |
+
return [self._process_single_file(payload)] # type: ignore
|
174 |
+
|
175 |
+
def _download_files(self, value: str | list[str]) -> str | list[str]:
|
176 |
+
downloaded_files = []
|
177 |
+
if isinstance(value, list):
|
178 |
+
for file in value:
|
179 |
+
if client_utils.is_http_url_like(file):
|
180 |
+
downloaded_file = processing_utils.save_url_to_cache(
|
181 |
+
file, self.GRADIO_CACHE
|
182 |
+
)
|
183 |
+
downloaded_files.append(downloaded_file)
|
184 |
+
else:
|
185 |
+
downloaded_files.append(file)
|
186 |
+
return downloaded_files
|
187 |
+
if client_utils.is_http_url_like(value):
|
188 |
+
downloaded_file = processing_utils.save_url_to_cache(
|
189 |
+
value, self.GRADIO_CACHE
|
190 |
+
)
|
191 |
+
return downloaded_file
|
192 |
else:
|
193 |
+
return value
|
|
|
|
|
|
|
194 |
|
195 |
def postprocess(self, value: str | list[str] | None) -> ListFiles | FileData | None:
|
196 |
+
"""
|
197 |
+
Parameters:
|
198 |
+
value: Expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
|
199 |
+
Returns:
|
200 |
+
molecule3d information as a FileData object, or a list of FileData objects.
|
201 |
+
"""
|
202 |
if value is None:
|
203 |
return None
|
204 |
+
value = self._download_files(value)
|
|
|
205 |
if isinstance(value, list):
|
206 |
return ListFiles(
|
207 |
root=[
|
|
|
220 |
size=Path(value).stat().st_size,
|
221 |
)
|
222 |
|
223 |
+
def process_example(self, value: str | list | None) -> str:
|
224 |
+
if value is None:
|
225 |
return ""
|
226 |
+
elif isinstance(value, list):
|
227 |
+
return ", ".join([Path(file).name for file in value])
|
228 |
else:
|
229 |
+
return Path(value).name
|
230 |
+
|
231 |
+
def example_payload(self) -> Any:
|
232 |
+
if self.file_count == "single":
|
233 |
+
return handle_file(
|
234 |
+
"https://files.rcsb.org/view/1PGA.pdb"
|
235 |
+
)
|
236 |
+
else:
|
237 |
+
return [
|
238 |
+
handle_file(
|
239 |
+
"https://files.rcsb.org/view/1PGA.pdb"
|
240 |
+
)
|
241 |
+
]
|
242 |
|
243 |
+
def example_value(self) -> Any:
|
244 |
if self.file_count == "single":
|
245 |
+
return "https://files.rcsb.org/view/1PGA.pdb"
|
246 |
else:
|
247 |
return [
|
248 |
+
"https://files.rcsb.org/view/1PGA.pdb"
|
249 |
]
|
src/backend/gradio_molecule3d/templates/component/index.js
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
src/backend/gradio_molecule3d/templates/component/style.css
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
src/backend/gradio_molecule3d/templates/example/index.js
CHANGED
@@ -1,53 +1,68 @@
|
|
1 |
const {
|
2 |
SvelteComponent: f,
|
3 |
-
|
4 |
-
attr:
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
7 |
init: g,
|
8 |
-
|
9 |
-
noop:
|
10 |
-
safe_not_equal:
|
11 |
-
set_data:
|
12 |
-
text:
|
13 |
-
toggle_class:
|
14 |
} = window.__gradio__svelte__internal;
|
15 |
-
function
|
16 |
-
let e, n = (
|
17 |
/*value*/
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
26 |
return {
|
27 |
c() {
|
28 |
-
e =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
e,
|
30 |
"table",
|
31 |
/*type*/
|
32 |
-
|
33 |
-
),
|
34 |
e,
|
35 |
"gallery",
|
36 |
/*type*/
|
37 |
-
|
38 |
-
),
|
39 |
e,
|
40 |
"selected",
|
41 |
/*selected*/
|
42 |
-
|
43 |
);
|
44 |
},
|
45 |
-
m(l,
|
46 |
-
|
47 |
},
|
48 |
-
p(l, [
|
49 |
-
|
50 |
-
1 && n !== (n =
|
|
|
51 |
/*value*/
|
52 |
l[0]
|
53 |
) ? (
|
@@ -56,44 +71,44 @@ function A(t) {
|
|
56 |
) : (
|
57 |
/*value*/
|
58 |
l[0]
|
59 |
-
)) + "") &&
|
60 |
-
2 &&
|
61 |
e,
|
62 |
"table",
|
63 |
/*type*/
|
64 |
l[1] === "table"
|
65 |
-
),
|
66 |
-
2 &&
|
67 |
e,
|
68 |
"gallery",
|
69 |
/*type*/
|
70 |
l[1] === "gallery"
|
71 |
-
),
|
72 |
-
4 &&
|
73 |
e,
|
74 |
"selected",
|
75 |
/*selected*/
|
76 |
l[2]
|
77 |
);
|
78 |
},
|
79 |
-
i:
|
80 |
-
o:
|
81 |
d(l) {
|
82 |
-
l &&
|
83 |
}
|
84 |
};
|
85 |
}
|
86 |
-
function
|
87 |
-
let { value:
|
88 |
-
return
|
89 |
-
"value" in
|
90 |
-
}, [
|
91 |
}
|
92 |
-
class
|
93 |
constructor(e) {
|
94 |
-
super(), g(this, e,
|
95 |
}
|
96 |
}
|
97 |
export {
|
98 |
-
|
99 |
};
|
|
|
1 |
const {
|
2 |
SvelteComponent: f,
|
3 |
+
append_hydration: o,
|
4 |
+
attr: u,
|
5 |
+
children: h,
|
6 |
+
claim_element: c,
|
7 |
+
claim_text: y,
|
8 |
+
detach: _,
|
9 |
+
element: v,
|
10 |
init: g,
|
11 |
+
insert_hydration: m,
|
12 |
+
noop: d,
|
13 |
+
safe_not_equal: b,
|
14 |
+
set_data: A,
|
15 |
+
text: j,
|
16 |
+
toggle_class: r
|
17 |
} = window.__gradio__svelte__internal;
|
18 |
+
function w(a) {
|
19 |
+
let e, n = (
|
20 |
/*value*/
|
21 |
+
(a[0] ? Array.isArray(
|
22 |
+
/*value*/
|
23 |
+
a[0]
|
24 |
+
) ? (
|
25 |
+
/*value*/
|
26 |
+
a[0].join(", ")
|
27 |
+
) : (
|
28 |
+
/*value*/
|
29 |
+
a[0]
|
30 |
+
) : "") + ""
|
31 |
+
), i;
|
32 |
return {
|
33 |
c() {
|
34 |
+
e = v("div"), i = j(n), this.h();
|
35 |
+
},
|
36 |
+
l(l) {
|
37 |
+
e = c(l, "DIV", { class: !0 });
|
38 |
+
var t = h(e);
|
39 |
+
i = y(t, n), t.forEach(_), this.h();
|
40 |
+
},
|
41 |
+
h() {
|
42 |
+
u(e, "class", "svelte-1hgn91n"), r(
|
43 |
e,
|
44 |
"table",
|
45 |
/*type*/
|
46 |
+
a[1] === "table"
|
47 |
+
), r(
|
48 |
e,
|
49 |
"gallery",
|
50 |
/*type*/
|
51 |
+
a[1] === "gallery"
|
52 |
+
), r(
|
53 |
e,
|
54 |
"selected",
|
55 |
/*selected*/
|
56 |
+
a[2]
|
57 |
);
|
58 |
},
|
59 |
+
m(l, t) {
|
60 |
+
m(l, e, t), o(e, i);
|
61 |
},
|
62 |
+
p(l, [t]) {
|
63 |
+
t & /*value*/
|
64 |
+
1 && n !== (n = /*value*/
|
65 |
+
(l[0] ? Array.isArray(
|
66 |
/*value*/
|
67 |
l[0]
|
68 |
) ? (
|
|
|
71 |
) : (
|
72 |
/*value*/
|
73 |
l[0]
|
74 |
+
) : "") + "") && A(i, n), t & /*type*/
|
75 |
+
2 && r(
|
76 |
e,
|
77 |
"table",
|
78 |
/*type*/
|
79 |
l[1] === "table"
|
80 |
+
), t & /*type*/
|
81 |
+
2 && r(
|
82 |
e,
|
83 |
"gallery",
|
84 |
/*type*/
|
85 |
l[1] === "gallery"
|
86 |
+
), t & /*selected*/
|
87 |
+
4 && r(
|
88 |
e,
|
89 |
"selected",
|
90 |
/*selected*/
|
91 |
l[2]
|
92 |
);
|
93 |
},
|
94 |
+
i: d,
|
95 |
+
o: d,
|
96 |
d(l) {
|
97 |
+
l && _(e);
|
98 |
}
|
99 |
};
|
100 |
}
|
101 |
+
function E(a, e, n) {
|
102 |
+
let { value: i } = e, { type: l } = e, { selected: t = !1 } = e;
|
103 |
+
return a.$$set = (s) => {
|
104 |
+
"value" in s && n(0, i = s.value), "type" in s && n(1, l = s.type), "selected" in s && n(2, t = s.selected);
|
105 |
+
}, [i, l, t];
|
106 |
}
|
107 |
+
class q extends f {
|
108 |
constructor(e) {
|
109 |
+
super(), g(this, e, E, w, b, { value: 0, type: 1, selected: 2 });
|
110 |
}
|
111 |
}
|
112 |
export {
|
113 |
+
q as default
|
114 |
};
|
src/demo/app.py
CHANGED
@@ -2,9 +2,8 @@
|
|
2 |
import gradio as gr
|
3 |
from gradio_molecule3d import Molecule3D
|
4 |
|
5 |
-
import os
|
6 |
|
7 |
-
example = Molecule3D().
|
8 |
|
9 |
|
10 |
reps = [
|
@@ -40,25 +39,18 @@ with gr.Blocks() as demo:
|
|
40 |
reps = [
|
41 |
{
|
42 |
"model": 0,
|
43 |
-
"chain": "",
|
44 |
-
"resname": "",
|
45 |
"style": "cartoon",
|
46 |
"color": "whiteCarbon",
|
47 |
"residue_range": "",
|
48 |
"around": 0,
|
49 |
"byres": False,
|
50 |
-
"visible": False,
|
51 |
},
|
52 |
{
|
53 |
"model": 0,
|
54 |
"chain": "A",
|
55 |
"resname": "HIS",
|
56 |
"style": "stick",
|
57 |
-
"color": "red"
|
58 |
-
"residue_range": "",
|
59 |
-
"around": 0,
|
60 |
-
"byres": False,
|
61 |
-
"visible": False,
|
62 |
}
|
63 |
]
|
64 |
</pre>
|
@@ -66,5 +58,5 @@ with gr.Blocks() as demo:
|
|
66 |
btn.click(predict, inputs=inp, outputs=out)
|
67 |
|
68 |
|
69 |
-
if __name__ ==
|
70 |
-
|
|
|
2 |
import gradio as gr
|
3 |
from gradio_molecule3d import Molecule3D
|
4 |
|
|
|
5 |
|
6 |
+
example = Molecule3D().example_value()
|
7 |
|
8 |
|
9 |
reps = [
|
|
|
39 |
reps = [
|
40 |
{
|
41 |
"model": 0,
|
|
|
|
|
42 |
"style": "cartoon",
|
43 |
"color": "whiteCarbon",
|
44 |
"residue_range": "",
|
45 |
"around": 0,
|
46 |
"byres": False,
|
|
|
47 |
},
|
48 |
{
|
49 |
"model": 0,
|
50 |
"chain": "A",
|
51 |
"resname": "HIS",
|
52 |
"style": "stick",
|
53 |
+
"color": "red"
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
]
|
56 |
</pre>
|
|
|
58 |
btn.click(predict, inputs=inp, outputs=out)
|
59 |
|
60 |
|
61 |
+
if __name__ == "__main__":
|
62 |
+
demo.launch()
|
src/demo/requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
gradio_molecule3d
|
src/demo/space.py
CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
-
_docs = {'Molecule3D': {'description': 'Creates a file component that allows uploading generic
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -24,7 +24,7 @@ with gr.Blocks(
|
|
24 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
25 |
</div>
|
26 |
|
27 |
-
|
28 |
""", elem_classes=["md-custom"], header_links=True)
|
29 |
app.render()
|
30 |
gr.Markdown(
|
@@ -42,9 +42,8 @@ pip install gradio_molecule3d
|
|
42 |
import gradio as gr
|
43 |
from gradio_molecule3d import Molecule3D
|
44 |
|
45 |
-
import os
|
46 |
|
47 |
-
example = Molecule3D().
|
48 |
|
49 |
|
50 |
reps = [
|
@@ -80,25 +79,18 @@ with gr.Blocks() as demo:
|
|
80 |
reps = [
|
81 |
{
|
82 |
"model": 0,
|
83 |
-
"chain": "",
|
84 |
-
"resname": "",
|
85 |
"style": "cartoon",
|
86 |
"color": "whiteCarbon",
|
87 |
"residue_range": "",
|
88 |
"around": 0,
|
89 |
"byres": False,
|
90 |
-
"visible": False,
|
91 |
},
|
92 |
{
|
93 |
"model": 0,
|
94 |
"chain": "A",
|
95 |
"resname": "HIS",
|
96 |
"style": "stick",
|
97 |
-
"color": "red"
|
98 |
-
"residue_range": "",
|
99 |
-
"around": 0,
|
100 |
-
"byres": False,
|
101 |
-
"visible": False,
|
102 |
}
|
103 |
]
|
104 |
</pre>
|
@@ -106,8 +98,8 @@ with gr.Blocks() as demo:
|
|
106 |
btn.click(predict, inputs=inp, outputs=out)
|
107 |
|
108 |
|
109 |
-
if __name__ ==
|
110 |
-
|
111 |
|
112 |
```
|
113 |
""", elem_classes=["md-custom"], header_links=True)
|
@@ -139,15 +131,12 @@ The impact on the users predict function varies depending on whether the compone
|
|
139 |
|
140 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
141 |
|
142 |
-
- **As input:** Is passed, the
|
143 |
-
- **As output:** Should return,
|
144 |
|
145 |
```python
|
146 |
def predict(
|
147 |
-
value: bytes
|
148 |
-
| gradio.utils.NamedString
|
149 |
-
| list[bytes | gradio.utils.NamedString]
|
150 |
-
| None
|
151 |
) -> str | list[str] | None:
|
152 |
return value
|
153 |
```
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'Molecule3D': {'description': 'Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output).\n', 'members': {'__init__': {'value': {'type': 'str | list[str] | Callable | None', 'default': 'None', 'description': 'Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.'}, 'reps': {'type': 'Any | None', 'default': '[]', 'description': None}, 'config': {'type': 'Any | None', 'default': '{\n "backgroundColor": "white",\n "orthographic": False,\n "disableFog": False,\n}', 'description': 'dictionary of config options'}, 'confidenceLabel': {'type': 'str | None', 'default': '"pLDDT"', 'description': 'label for confidence values stored in the bfactor column of a pdb file'}, 'file_count': {'type': 'Literal["single", "multiple", "directory"]', 'default': '"single"', 'description': 'if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".'}, 'file_types': {'type': 'list[str] | None', 'default': 'None', 'description': 'List of file extensions or types of files to be uploaded (e.g. [\'image\', \'.json\', \'.mp4\']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.'}, 'type': {'type': 'Literal["filepath", "binary"]', 'default': '"filepath"', 'description': 'Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.'}, 'every': {'type': 'Timer | float | None', 'default': 'None', 'description': 'Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.'}, 'inputs': {'type': 'Component | Sequence[Component] | set[Component] | None', 'default': 'None', 'description': 'Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.'}, 'show_label': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will display label.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, will place the component in a container - providing some extra padding around the border.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.'}, 'min_width': {'type': 'int', 'default': '160', 'description': 'minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.'}, 'height': {'type': 'int | float | None', 'default': 'None', 'description': 'The maximum height of the file component, specified in pixels if a number is passed, or in CSS units if a string is passed. If more files are uploaded than can fit in the height, a scrollbar will appear.'}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': 'if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, component will be hidden.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles.'}, 'render': {'type': 'bool', 'default': 'True', 'description': 'If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later.'}, 'key': {'type': 'int | str | None', 'default': 'None', 'description': 'if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved.'}, 'showviewer': {'type': 'bool', 'default': 'True', 'description': 'If True, will display the 3Dmol.js viewer. If False, will not display the 3Dmol.js viewer.'}}, 'postprocess': {'value': {'type': 'str | list[str] | None', 'description': 'Expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.'}}, 'preprocess': {'return': {'type': 'bytes | str | list[bytes] | list[str] | None', 'description': 'Passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the Molecule3D changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'select': {'type': None, 'default': None, 'description': 'Event listener for when the user selects or deselects the Molecule3D. Uses event data gradio.SelectData to carry `value` referring to the label of the Molecule3D, and `selected` to refer to state of the Molecule3D. See EventData documentation on how to use this event data'}, 'clear': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clears the Molecule3D using the clear button for the component.'}, 'upload': {'type': None, 'default': None, 'description': 'This listener is triggered when the user uploads a file into the Molecule3D.'}, 'delete': {'type': None, 'default': None, 'description': 'This listener is triggered when the user deletes and item from the Molecule3D. Uses event data gradio.DeletedFileData to carry `value` referring to the file that was deleted as an instance of FileData. See EventData documentation on how to use this event data'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'Molecule3D': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
24 |
<a href="https://pypi.org/project/gradio_molecule3d/" target="_blank"><img alt="PyPI - Version" src="https://img.shields.io/pypi/v/gradio_molecule3d"></a>
|
25 |
</div>
|
26 |
|
27 |
+
Python library for easily interacting with trained machine learning models
|
28 |
""", elem_classes=["md-custom"], header_links=True)
|
29 |
app.render()
|
30 |
gr.Markdown(
|
|
|
42 |
import gradio as gr
|
43 |
from gradio_molecule3d import Molecule3D
|
44 |
|
|
|
45 |
|
46 |
+
example = Molecule3D().example_value()
|
47 |
|
48 |
|
49 |
reps = [
|
|
|
79 |
reps = [
|
80 |
{
|
81 |
"model": 0,
|
|
|
|
|
82 |
"style": "cartoon",
|
83 |
"color": "whiteCarbon",
|
84 |
"residue_range": "",
|
85 |
"around": 0,
|
86 |
"byres": False,
|
|
|
87 |
},
|
88 |
{
|
89 |
"model": 0,
|
90 |
"chain": "A",
|
91 |
"resname": "HIS",
|
92 |
"style": "stick",
|
93 |
+
"color": "red"
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
]
|
96 |
</pre>
|
|
|
98 |
btn.click(predict, inputs=inp, outputs=out)
|
99 |
|
100 |
|
101 |
+
if __name__ == "__main__":
|
102 |
+
demo.launch()
|
103 |
|
104 |
```
|
105 |
""", elem_classes=["md-custom"], header_links=True)
|
|
|
131 |
|
132 |
The code snippet below is accurate in cases where the component is used as both an input and an output.
|
133 |
|
134 |
+
- **As input:** Is passed, passes the file as a `str` or `bytes` object, or a list of `str` or list of `bytes` objects, depending on `type` and `file_count`.
|
135 |
+
- **As output:** Should return, expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
|
136 |
|
137 |
```python
|
138 |
def predict(
|
139 |
+
value: bytes | str | list[bytes] | list[str] | None
|
|
|
|
|
|
|
140 |
) -> str | list[str] | None:
|
141 |
return value
|
142 |
```
|
src/frontend/Example.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import type { FileData } from "@gradio/client";
|
3 |
|
4 |
-
export let value: FileData;
|
5 |
export let type: "gallery" | "table";
|
6 |
export let selected = false;
|
7 |
</script>
|
@@ -11,7 +11,7 @@
|
|
11 |
class:gallery={type === "gallery"}
|
12 |
class:selected
|
13 |
>
|
14 |
-
{Array.isArray(value) ? value.join(", ") : value}
|
15 |
</div>
|
16 |
|
17 |
<style>
|
|
|
1 |
<script lang="ts">
|
2 |
import type { FileData } from "@gradio/client";
|
3 |
|
4 |
+
export let value: FileData | null;
|
5 |
export let type: "gallery" | "table";
|
6 |
export let selected = false;
|
7 |
</script>
|
|
|
11 |
class:gallery={type === "gallery"}
|
12 |
class:selected
|
13 |
>
|
14 |
+
{value ? (Array.isArray(value) ? value.join(", ") : value) : ""}
|
15 |
</div>
|
16 |
|
17 |
<style>
|
src/frontend/Index.svelte
CHANGED
@@ -8,27 +8,34 @@
|
|
8 |
</script>
|
9 |
|
10 |
<script lang="ts">
|
|
|
|
|
11 |
import type { Gradio, SelectData } from "@gradio/utils";
|
12 |
import File from "./shared/File.svelte";
|
13 |
import FileUpload from "./shared/FileUpload.svelte";
|
14 |
-
import {
|
15 |
import { Block, UploadText } from "@gradio/atoms";
|
|
|
16 |
import { StatusTracker } from "@gradio/statustracker";
|
17 |
import type { LoadingStatus } from "@gradio/statustracker";
|
|
|
18 |
export let elem_id = "";
|
19 |
export let elem_classes: string[] = [];
|
20 |
export let visible = true;
|
21 |
export let value: null | FileData | FileData[];
|
|
|
22 |
export let interactive: boolean;
|
23 |
export let root: string;
|
24 |
export let label: string;
|
25 |
export let show_label: boolean;
|
26 |
export let height: number | undefined = undefined;
|
|
|
27 |
//Molecule3D specific arguments
|
28 |
export let reps: any = [];
|
29 |
export let config: any = {};
|
30 |
export let confidenceLabel: string = "";
|
31 |
export let showviewer: boolean = true;
|
|
|
32 |
export let _selectable = false;
|
33 |
export let loading_status: LoadingStatus;
|
34 |
export let container = true;
|
@@ -40,20 +47,24 @@
|
|
40 |
upload: never;
|
41 |
clear: never;
|
42 |
select: SelectData;
|
|
|
|
|
43 |
}>;
|
44 |
-
export let file_count:
|
45 |
export let file_types: string[] = ["file"];
|
|
|
46 |
let old_value = value;
|
47 |
$: if (JSON.stringify(old_value) !== JSON.stringify(value)) {
|
48 |
gradio.dispatch("change");
|
49 |
old_value = value;
|
50 |
-
|
51 |
moldata = null;
|
52 |
retrieveContent(value);
|
53 |
}
|
|
|
54 |
let dragging = false;
|
55 |
let pending_upload = false;
|
56 |
-
|
57 |
let keys_for_reps = {
|
58 |
model: {
|
59 |
type: Number,
|
@@ -198,7 +209,7 @@
|
|
198 |
|
199 |
<Block
|
200 |
{visible}
|
201 |
-
variant={value
|
202 |
border_mode={dragging ? "focus" : "base"}
|
203 |
padding={false}
|
204 |
{elem_id}
|
@@ -215,8 +226,8 @@
|
|
215 |
status={pending_upload
|
216 |
? "generating"
|
217 |
: loading_status?.status || "complete"}
|
|
|
218 |
/>
|
219 |
-
|
220 |
{#if !interactive}
|
221 |
<File
|
222 |
on:select={({ detail }) => gradio.dispatch("select", detail)}
|
@@ -235,6 +246,8 @@
|
|
235 |
/>
|
236 |
{:else}
|
237 |
<FileUpload
|
|
|
|
|
238 |
{label}
|
239 |
{show_label}
|
240 |
{value}
|
@@ -248,8 +261,8 @@
|
|
248 |
{confidenceLabel}
|
249 |
{moldata}
|
250 |
molviewer={showviewer}
|
|
|
251 |
on:change={({ detail }) => {
|
252 |
-
errors = [];
|
253 |
value = detail;
|
254 |
}}
|
255 |
on:drag={({ detail }) => (dragging = detail)}
|
@@ -261,6 +274,14 @@
|
|
261 |
"identifier not found in database, check spelling"
|
262 |
)}
|
263 |
on:upload={() => gradio.dispatch("upload")}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
i18n={gradio.i18n}
|
265 |
>
|
266 |
<UploadText i18n={gradio.i18n} type="file" />
|
@@ -301,93 +322,3 @@
|
|
301 |
</div>
|
302 |
{/if}
|
303 |
</Block>
|
304 |
-
|
305 |
-
<style>
|
306 |
-
.sr-only {
|
307 |
-
position: absolute;
|
308 |
-
width: 1px;
|
309 |
-
height: 1px;
|
310 |
-
padding: 0;
|
311 |
-
margin: -1px;
|
312 |
-
overflow: hidden;
|
313 |
-
clip: rect(0, 0, 0, 0);
|
314 |
-
white-space: nowrap;
|
315 |
-
border-width: 0;
|
316 |
-
}
|
317 |
-
.mb-4 {
|
318 |
-
margin-bottom: 1rem;
|
319 |
-
}
|
320 |
-
.ml-4 {
|
321 |
-
margin-left: 1rem;
|
322 |
-
}
|
323 |
-
.mr-3 {
|
324 |
-
margin-right: 0.75rem;
|
325 |
-
}
|
326 |
-
.mt-1 {
|
327 |
-
margin-top: 0.25rem;
|
328 |
-
}
|
329 |
-
.mt-1\.5 {
|
330 |
-
margin-top: 0.375rem;
|
331 |
-
}
|
332 |
-
.mt-\[2px\] {
|
333 |
-
margin-top: 2px;
|
334 |
-
}
|
335 |
-
.inline {
|
336 |
-
display: inline;
|
337 |
-
}
|
338 |
-
.flex {
|
339 |
-
display: flex;
|
340 |
-
}
|
341 |
-
.h-4 {
|
342 |
-
height: 1rem;
|
343 |
-
}
|
344 |
-
.w-4 {
|
345 |
-
width: 1rem;
|
346 |
-
}
|
347 |
-
.flex-shrink-0 {
|
348 |
-
flex-shrink: 0;
|
349 |
-
}
|
350 |
-
.list-inside {
|
351 |
-
list-style-position: inside;
|
352 |
-
}
|
353 |
-
.list-disc {
|
354 |
-
list-style-type: disc;
|
355 |
-
}
|
356 |
-
.rounded-lg {
|
357 |
-
border-radius: 0.5rem;
|
358 |
-
}
|
359 |
-
.bg-red-50 {
|
360 |
-
--tw-bg-opacity: 1;
|
361 |
-
background-color: rgb(254 242 242 / var(--tw-bg-opacity));
|
362 |
-
}
|
363 |
-
.m-2 {
|
364 |
-
margin: 0.5rem;
|
365 |
-
}
|
366 |
-
.p-4 {
|
367 |
-
padding: 1rem;
|
368 |
-
}
|
369 |
-
.text-sm {
|
370 |
-
font-size: 0.875rem;
|
371 |
-
line-height: 1.25rem;
|
372 |
-
}
|
373 |
-
.font-medium {
|
374 |
-
font-weight: 500;
|
375 |
-
}
|
376 |
-
.lowercase {
|
377 |
-
text-transform: lowercase;
|
378 |
-
}
|
379 |
-
.text-red-800 {
|
380 |
-
--tw-text-opacity: 1;
|
381 |
-
color: rgb(153 27 27 / var(--tw-text-opacity));
|
382 |
-
}
|
383 |
-
@media (prefers-color-scheme: dark) {
|
384 |
-
.dark\:bg-gray-800 {
|
385 |
-
--tw-bg-opacity: 1;
|
386 |
-
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
387 |
-
}
|
388 |
-
.dark\:text-red-400 {
|
389 |
-
--tw-text-opacity: 1;
|
390 |
-
color: rgb(248 113 113 / var(--tw-text-opacity));
|
391 |
-
}
|
392 |
-
}
|
393 |
-
</style>
|
|
|
8 |
</script>
|
9 |
|
10 |
<script lang="ts">
|
11 |
+
import "./style.css";
|
12 |
+
|
13 |
import type { Gradio, SelectData } from "@gradio/utils";
|
14 |
import File from "./shared/File.svelte";
|
15 |
import FileUpload from "./shared/FileUpload.svelte";
|
16 |
+
import type { FileData } from "@gradio/client";
|
17 |
import { Block, UploadText } from "@gradio/atoms";
|
18 |
+
|
19 |
import { StatusTracker } from "@gradio/statustracker";
|
20 |
import type { LoadingStatus } from "@gradio/statustracker";
|
21 |
+
|
22 |
export let elem_id = "";
|
23 |
export let elem_classes: string[] = [];
|
24 |
export let visible = true;
|
25 |
export let value: null | FileData | FileData[];
|
26 |
+
|
27 |
export let interactive: boolean;
|
28 |
export let root: string;
|
29 |
export let label: string;
|
30 |
export let show_label: boolean;
|
31 |
export let height: number | undefined = undefined;
|
32 |
+
|
33 |
//Molecule3D specific arguments
|
34 |
export let reps: any = [];
|
35 |
export let config: any = {};
|
36 |
export let confidenceLabel: string = "";
|
37 |
export let showviewer: boolean = true;
|
38 |
+
|
39 |
export let _selectable = false;
|
40 |
export let loading_status: LoadingStatus;
|
41 |
export let container = true;
|
|
|
47 |
upload: never;
|
48 |
clear: never;
|
49 |
select: SelectData;
|
50 |
+
clear_status: LoadingStatus;
|
51 |
+
delete: FileData;
|
52 |
}>;
|
53 |
+
export let file_count: "single" | "multiple" | "directory";
|
54 |
export let file_types: string[] = ["file"];
|
55 |
+
|
56 |
let old_value = value;
|
57 |
$: if (JSON.stringify(old_value) !== JSON.stringify(value)) {
|
58 |
gradio.dispatch("change");
|
59 |
old_value = value;
|
60 |
+
|
61 |
moldata = null;
|
62 |
retrieveContent(value);
|
63 |
}
|
64 |
+
|
65 |
let dragging = false;
|
66 |
let pending_upload = false;
|
67 |
+
|
68 |
let keys_for_reps = {
|
69 |
model: {
|
70 |
type: Number,
|
|
|
209 |
|
210 |
<Block
|
211 |
{visible}
|
212 |
+
variant={value ? "solid" : "dashed"}
|
213 |
border_mode={dragging ? "focus" : "base"}
|
214 |
padding={false}
|
215 |
{elem_id}
|
|
|
226 |
status={pending_upload
|
227 |
? "generating"
|
228 |
: loading_status?.status || "complete"}
|
229 |
+
on:clear_status={() => gradio.dispatch("clear_status", loading_status)}
|
230 |
/>
|
|
|
231 |
{#if !interactive}
|
232 |
<File
|
233 |
on:select={({ detail }) => gradio.dispatch("select", detail)}
|
|
|
246 |
/>
|
247 |
{:else}
|
248 |
<FileUpload
|
249 |
+
upload={gradio.client.upload}
|
250 |
+
stream_handler={gradio.client.stream}
|
251 |
{label}
|
252 |
{show_label}
|
253 |
{value}
|
|
|
261 |
{confidenceLabel}
|
262 |
{moldata}
|
263 |
molviewer={showviewer}
|
264 |
+
max_file_size={gradio.max_file_size}
|
265 |
on:change={({ detail }) => {
|
|
|
266 |
value = detail;
|
267 |
}}
|
268 |
on:drag={({ detail }) => (dragging = detail)}
|
|
|
274 |
"identifier not found in database, check spelling"
|
275 |
)}
|
276 |
on:upload={() => gradio.dispatch("upload")}
|
277 |
+
on:error={({ detail }) => {
|
278 |
+
loading_status = loading_status || {};
|
279 |
+
loading_status.status = "error";
|
280 |
+
gradio.dispatch("error", detail);
|
281 |
+
}}
|
282 |
+
on:delete={({ detail }) => {
|
283 |
+
gradio.dispatch("delete", detail);
|
284 |
+
}}
|
285 |
i18n={gradio.i18n}
|
286 |
>
|
287 |
<UploadText i18n={gradio.i18n} type="file" />
|
|
|
322 |
</div>
|
323 |
{/if}
|
324 |
</Block>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/frontend/gradio.config.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import tailwindcss from "@tailwindcss/vite";
|
2 |
+
|
3 |
+
export default {
|
4 |
+
plugins: [tailwindcss()],
|
5 |
+
svelte: {
|
6 |
+
preprocess: [],
|
7 |
+
},
|
8 |
+
build: {
|
9 |
+
target: "modules",
|
10 |
+
},
|
11 |
+
};
|
src/frontend/package-lock.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
src/frontend/package.json
CHANGED
@@ -1,25 +1,36 @@
|
|
1 |
{
|
2 |
"name": "gradio_molecule3d",
|
3 |
-
"version": "0.2
|
4 |
"description": "Gradio UI packages",
|
5 |
"type": "module",
|
6 |
"author": "",
|
7 |
"license": "ISC",
|
8 |
"private": false,
|
9 |
"dependencies": {
|
10 |
-
"@gradio/atoms": "0.
|
11 |
-
"@gradio/client": "
|
12 |
-
"@gradio/icons": "0.
|
13 |
-
"@gradio/
|
14 |
-
"@gradio/
|
15 |
-
"@gradio/
|
16 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
},
|
18 |
"main": "./Index.svelte",
|
19 |
"main_changeset": true,
|
20 |
"exports": {
|
21 |
-
".":
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
"./package.json": "./package.json"
|
24 |
}
|
25 |
-
}
|
|
|
1 |
{
|
2 |
"name": "gradio_molecule3d",
|
3 |
+
"version": "0.9.2",
|
4 |
"description": "Gradio UI packages",
|
5 |
"type": "module",
|
6 |
"author": "",
|
7 |
"license": "ISC",
|
8 |
"private": false,
|
9 |
"dependencies": {
|
10 |
+
"@gradio/atoms": "0.9.0",
|
11 |
+
"@gradio/client": "1.6.0",
|
12 |
+
"@gradio/icons": "0.8.0",
|
13 |
+
"@gradio/markdown": "^0.10.1",
|
14 |
+
"@gradio/statustracker": "0.8.1",
|
15 |
+
"@gradio/upload": "0.13.1",
|
16 |
+
"@gradio/utils": "0.7.0",
|
17 |
+
"@gradio/wasm": "0.14.1",
|
18 |
+
"@tailwindcss/vite": "^4.0.0-alpha.30",
|
19 |
+
"3dmol": "^2.4.0",
|
20 |
+
"tailwindcss": "^4.0.0-alpha.30"
|
21 |
+
},
|
22 |
+
"devDependencies": {
|
23 |
+
"@gradio/preview": "0.12.0"
|
24 |
},
|
25 |
"main": "./Index.svelte",
|
26 |
"main_changeset": true,
|
27 |
"exports": {
|
28 |
+
".": {
|
29 |
+
"gradio": "./Index.svelte"
|
30 |
+
},
|
31 |
+
"./example": {
|
32 |
+
"gradio": "./Example.svelte"
|
33 |
+
},
|
34 |
"./package.json": "./package.json"
|
35 |
}
|
36 |
+
}
|
src/frontend/shared/File.svelte
CHANGED
@@ -3,23 +3,22 @@
|
|
3 |
import { BlockLabel, Empty } from "@gradio/atoms";
|
4 |
import { File } from "@gradio/icons";
|
5 |
import FilePreview from "./FilePreview.svelte";
|
|
|
6 |
|
7 |
import MolecularViewer from "./MolecularViewer.svelte";
|
8 |
|
9 |
-
import type { I18nFormatter } from "@gradio/utils";
|
10 |
-
|
11 |
export let value: FileData | FileData[] | null = null;
|
12 |
export let label: string;
|
13 |
export let show_label = true;
|
14 |
export let selectable = false;
|
15 |
export let height: number | undefined = undefined;
|
16 |
export let i18n: I18nFormatter;
|
|
|
17 |
export let config = {};
|
18 |
export let confidenceLabel = "";
|
19 |
export let representations = [];
|
20 |
export let moldata = null;
|
21 |
export let molviewer = false;
|
22 |
-
export let errors = [];
|
23 |
</script>
|
24 |
|
25 |
<BlockLabel
|
@@ -29,10 +28,9 @@
|
|
29 |
label={label || "File"}
|
30 |
/>
|
31 |
|
32 |
-
{#if value}
|
33 |
<FilePreview {i18n} {selectable} on:select {value} {height} />
|
34 |
|
35 |
-
<!-- {JSON.stringify(moldata)} -->
|
36 |
{#if moldata != null && molviewer}
|
37 |
<MolecularViewer {moldata} {config} {confidenceLabel} {representations} />
|
38 |
{/if}
|
|
|
3 |
import { BlockLabel, Empty } from "@gradio/atoms";
|
4 |
import { File } from "@gradio/icons";
|
5 |
import FilePreview from "./FilePreview.svelte";
|
6 |
+
import type { I18nFormatter } from "@gradio/utils";
|
7 |
|
8 |
import MolecularViewer from "./MolecularViewer.svelte";
|
9 |
|
|
|
|
|
10 |
export let value: FileData | FileData[] | null = null;
|
11 |
export let label: string;
|
12 |
export let show_label = true;
|
13 |
export let selectable = false;
|
14 |
export let height: number | undefined = undefined;
|
15 |
export let i18n: I18nFormatter;
|
16 |
+
|
17 |
export let config = {};
|
18 |
export let confidenceLabel = "";
|
19 |
export let representations = [];
|
20 |
export let moldata = null;
|
21 |
export let molviewer = false;
|
|
|
22 |
</script>
|
23 |
|
24 |
<BlockLabel
|
|
|
28 |
label={label || "File"}
|
29 |
/>
|
30 |
|
31 |
+
{#if value && (Array.isArray(value) ? value.length > 0 : true)}
|
32 |
<FilePreview {i18n} {selectable} on:select {value} {height} />
|
33 |
|
|
|
34 |
{#if moldata != null && molviewer}
|
35 |
<MolecularViewer {moldata} {config} {confidenceLabel} {representations} />
|
36 |
{/if}
|
src/frontend/shared/FilePreview.svelte
CHANGED
@@ -1,16 +1,60 @@
|
|
1 |
<script lang="ts">
|
2 |
import type { FileData } from "@gradio/client";
|
3 |
-
import {
|
4 |
import { createEventDispatcher } from "svelte";
|
5 |
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
|
|
6 |
|
7 |
const dispatch = createEventDispatcher<{
|
8 |
select: SelectData;
|
|
|
|
|
9 |
}>();
|
10 |
export let value: FileData | FileData[];
|
11 |
export let selectable = false;
|
12 |
export let height: number | undefined = undefined;
|
13 |
export let i18n: I18nFormatter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
</script>
|
15 |
|
16 |
<div
|
@@ -19,33 +63,51 @@
|
|
19 |
>
|
20 |
<table class="file-preview">
|
21 |
<tbody>
|
22 |
-
{#each
|
23 |
<tr
|
24 |
class="file"
|
25 |
class:selectable
|
26 |
-
on:click={() =>
|
27 |
-
|
28 |
-
|
29 |
-
index: i
|
30 |
-
})}
|
31 |
>
|
32 |
-
<td>
|
33 |
-
{
|
|
|
34 |
</td>
|
35 |
|
36 |
<td class="download">
|
37 |
{#if file.url}
|
38 |
-
<
|
39 |
href={file.url}
|
40 |
-
target="_blank"
|
41 |
download={window.__is_colab__ ? null : file.orig_name}
|
42 |
>
|
43 |
-
{@html
|
44 |
-
|
|
|
|
|
45 |
{:else}
|
46 |
{i18n("file.uploading")}
|
47 |
{/if}
|
48 |
</td>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
</tr>
|
50 |
{/each}
|
51 |
</tbody>
|
@@ -53,26 +115,31 @@
|
|
53 |
</div>
|
54 |
|
55 |
<style>
|
56 |
-
|
57 |
-
|
|
|
|
|
58 |
}
|
59 |
|
60 |
-
|
61 |
-
|
62 |
-
text-align: right;
|
63 |
-
}
|
64 |
-
.file-preview-holder {
|
65 |
-
overflow-x: auto;
|
66 |
-
overflow-y: auto;
|
67 |
}
|
|
|
68 |
.file-preview {
|
|
|
69 |
width: var(--size-full);
|
70 |
max-height: var(--size-60);
|
71 |
overflow-y: auto;
|
72 |
margin-top: var(--size-1);
|
73 |
color: var(--body-text-color);
|
74 |
}
|
|
|
|
|
|
|
|
|
|
|
75 |
.file {
|
|
|
76 |
width: var(--size-full);
|
77 |
}
|
78 |
|
@@ -80,20 +147,40 @@
|
|
80 |
padding: var(--size-1) var(--size-2-5);
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
.download:hover {
|
84 |
text-decoration: underline;
|
85 |
}
|
86 |
-
.download > a {
|
87 |
color: var(--link-text-color);
|
88 |
}
|
89 |
|
90 |
-
.download > a:hover {
|
91 |
color: var(--link-text-color-hover);
|
92 |
}
|
93 |
-
.download > a:visited {
|
94 |
color: var(--link-text-color-visited);
|
95 |
}
|
96 |
-
.download > a:active {
|
97 |
color: var(--link-text-color-active);
|
98 |
}
|
99 |
.selectable {
|
|
|
1 |
<script lang="ts">
|
2 |
import type { FileData } from "@gradio/client";
|
3 |
+
import { prettyBytes } from "./utils";
|
4 |
import { createEventDispatcher } from "svelte";
|
5 |
import type { I18nFormatter, SelectData } from "@gradio/utils";
|
6 |
+
import { DownloadLink } from "@gradio/wasm/svelte";
|
7 |
|
8 |
const dispatch = createEventDispatcher<{
|
9 |
select: SelectData;
|
10 |
+
change: FileData[] | FileData;
|
11 |
+
delete: FileData;
|
12 |
}>();
|
13 |
export let value: FileData | FileData[];
|
14 |
export let selectable = false;
|
15 |
export let height: number | undefined = undefined;
|
16 |
export let i18n: I18nFormatter;
|
17 |
+
|
18 |
+
function split_filename(filename: string): [string, string] {
|
19 |
+
const last_dot = filename.lastIndexOf(".");
|
20 |
+
if (last_dot === -1) {
|
21 |
+
return [filename, ""];
|
22 |
+
}
|
23 |
+
return [filename.slice(0, last_dot), filename.slice(last_dot)];
|
24 |
+
}
|
25 |
+
|
26 |
+
$: normalized_files = (Array.isArray(value) ? value : [value]).map((file) => {
|
27 |
+
const [filename_stem, filename_ext] = split_filename(file.orig_name ?? "");
|
28 |
+
return {
|
29 |
+
...file,
|
30 |
+
filename_stem,
|
31 |
+
filename_ext
|
32 |
+
};
|
33 |
+
});
|
34 |
+
|
35 |
+
function handle_row_click(
|
36 |
+
event: MouseEvent & { currentTarget: HTMLTableRowElement },
|
37 |
+
index: number
|
38 |
+
): void {
|
39 |
+
const tr = event.currentTarget;
|
40 |
+
const should_select =
|
41 |
+
event.target === tr || // Only select if the click is on the row itself
|
42 |
+
(tr &&
|
43 |
+
tr.firstElementChild &&
|
44 |
+
event.composedPath().includes(tr.firstElementChild)); // Or if the click is on the name column
|
45 |
+
|
46 |
+
if (should_select) {
|
47 |
+
dispatch("select", { value: normalized_files[index].orig_name, index });
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
function remove_file(index: number): void {
|
52 |
+
const removed = normalized_files.splice(index, 1);
|
53 |
+
normalized_files = [...normalized_files];
|
54 |
+
value = normalized_files;
|
55 |
+
dispatch("delete", removed[0]);
|
56 |
+
dispatch("change", normalized_files);
|
57 |
+
}
|
58 |
</script>
|
59 |
|
60 |
<div
|
|
|
63 |
>
|
64 |
<table class="file-preview">
|
65 |
<tbody>
|
66 |
+
{#each normalized_files as file, i (file)}
|
67 |
<tr
|
68 |
class="file"
|
69 |
class:selectable
|
70 |
+
on:click={(event) => {
|
71 |
+
handle_row_click(event, i);
|
72 |
+
}}
|
|
|
|
|
73 |
>
|
74 |
+
<td class="filename" aria-label={file.orig_name}>
|
75 |
+
<span class="stem">{file.filename_stem}</span>
|
76 |
+
<span class="ext">{file.filename_ext}</span>
|
77 |
</td>
|
78 |
|
79 |
<td class="download">
|
80 |
{#if file.url}
|
81 |
+
<DownloadLink
|
82 |
href={file.url}
|
|
|
83 |
download={window.__is_colab__ ? null : file.orig_name}
|
84 |
>
|
85 |
+
{@html file.size != null
|
86 |
+
? prettyBytes(file.size)
|
87 |
+
: "(size unknown)"} ⇣
|
88 |
+
</DownloadLink>
|
89 |
{:else}
|
90 |
{i18n("file.uploading")}
|
91 |
{/if}
|
92 |
</td>
|
93 |
+
|
94 |
+
{#if normalized_files.length > 1}
|
95 |
+
<td>
|
96 |
+
<button
|
97 |
+
class="label-clear-button"
|
98 |
+
aria-label="Remove this file"
|
99 |
+
on:click={() => {
|
100 |
+
remove_file(i);
|
101 |
+
}}
|
102 |
+
on:keydown={(event) => {
|
103 |
+
if (event.key === "Enter") {
|
104 |
+
remove_file(i);
|
105 |
+
}
|
106 |
+
}}
|
107 |
+
>×
|
108 |
+
</button>
|
109 |
+
</td>
|
110 |
+
{/if}
|
111 |
</tr>
|
112 |
{/each}
|
113 |
</tbody>
|
|
|
115 |
</div>
|
116 |
|
117 |
<style>
|
118 |
+
.label-clear-button {
|
119 |
+
color: var(--body-text-color-subdued);
|
120 |
+
position: relative;
|
121 |
+
left: -3px;
|
122 |
}
|
123 |
|
124 |
+
.label-clear-button:hover {
|
125 |
+
color: var(--body-text-color);
|
|
|
|
|
|
|
|
|
|
|
126 |
}
|
127 |
+
|
128 |
.file-preview {
|
129 |
+
table-layout: fixed;
|
130 |
width: var(--size-full);
|
131 |
max-height: var(--size-60);
|
132 |
overflow-y: auto;
|
133 |
margin-top: var(--size-1);
|
134 |
color: var(--body-text-color);
|
135 |
}
|
136 |
+
|
137 |
+
.file-preview-holder {
|
138 |
+
overflow: auto;
|
139 |
+
}
|
140 |
+
|
141 |
.file {
|
142 |
+
display: flex;
|
143 |
width: var(--size-full);
|
144 |
}
|
145 |
|
|
|
147 |
padding: var(--size-1) var(--size-2-5);
|
148 |
}
|
149 |
|
150 |
+
.filename {
|
151 |
+
flex-grow: 1;
|
152 |
+
display: flex;
|
153 |
+
overflow: hidden;
|
154 |
+
}
|
155 |
+
.filename .stem {
|
156 |
+
overflow: hidden;
|
157 |
+
text-overflow: ellipsis;
|
158 |
+
white-space: nowrap;
|
159 |
+
}
|
160 |
+
.filename .ext {
|
161 |
+
white-space: nowrap;
|
162 |
+
}
|
163 |
+
|
164 |
+
.download {
|
165 |
+
min-width: 8rem;
|
166 |
+
width: 10%;
|
167 |
+
white-space: nowrap;
|
168 |
+
text-align: right;
|
169 |
+
}
|
170 |
.download:hover {
|
171 |
text-decoration: underline;
|
172 |
}
|
173 |
+
.download > :global(a) {
|
174 |
color: var(--link-text-color);
|
175 |
}
|
176 |
|
177 |
+
.download > :global(a:hover) {
|
178 |
color: var(--link-text-color-hover);
|
179 |
}
|
180 |
+
.download > :global(a:visited) {
|
181 |
color: var(--link-text-color-visited);
|
182 |
}
|
183 |
+
.download > :global(a:active) {
|
184 |
color: var(--link-text-color-active);
|
185 |
}
|
186 |
.selectable {
|
src/frontend/shared/FileRetrieval.svelte
CHANGED
@@ -1,16 +1,19 @@
|
|
1 |
<script lang="ts">
|
2 |
import { createEventDispatcher, tick, getContext } from "svelte";
|
3 |
|
4 |
-
import {
|
5 |
import LoadingSpinner from "./loading_spinner.svelte";
|
6 |
let uploaded_files;
|
7 |
const dispatch = createEventDispatcher();
|
8 |
-
|
|
|
|
|
|
|
9 |
export let root: string;
|
10 |
async function handle_upload(file_data: FileData): Promise<void> {
|
11 |
await tick();
|
12 |
const upload_id = Math.random().toString(36).substring(2, 15);
|
13 |
-
uploaded_files = await upload([file_data], root, upload_id
|
14 |
dispatch("load", uploaded_files[0]);
|
15 |
}
|
16 |
let loading = false;
|
|
|
1 |
<script lang="ts">
|
2 |
import { createEventDispatcher, tick, getContext } from "svelte";
|
3 |
|
4 |
+
import { FileData } from "@gradio/client";
|
5 |
import LoadingSpinner from "./loading_spinner.svelte";
|
6 |
let uploaded_files;
|
7 |
const dispatch = createEventDispatcher();
|
8 |
+
|
9 |
+
import type { Client } from "@Gradio Uptime/client";
|
10 |
+
export let upload: Client["upload"];
|
11 |
+
|
12 |
export let root: string;
|
13 |
async function handle_upload(file_data: FileData): Promise<void> {
|
14 |
await tick();
|
15 |
const upload_id = Math.random().toString(36).substring(2, 15);
|
16 |
+
uploaded_files = await upload([file_data], root, upload_id);
|
17 |
dispatch("load", uploaded_files[0]);
|
18 |
}
|
19 |
let loading = false;
|
src/frontend/shared/FileUpload.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import { createEventDispatcher, tick } from "svelte";
|
3 |
import { Upload, ModifyUpload } from "@gradio/upload";
|
4 |
-
import type { FileData } from "@gradio/client";
|
5 |
import { BlockLabel } from "@gradio/atoms";
|
6 |
import { File } from "@gradio/icons";
|
7 |
import FileRetrieval from "./FileRetrieval.svelte";
|
@@ -14,12 +14,15 @@
|
|
14 |
|
15 |
export let label: string;
|
16 |
export let show_label = true;
|
17 |
-
export let file_count = "single";
|
18 |
export let file_types: string[] | null = null;
|
19 |
export let selectable = false;
|
20 |
export let root: string;
|
21 |
export let height: number | undefined = undefined;
|
22 |
export let i18n: I18nFormatter;
|
|
|
|
|
|
|
23 |
|
24 |
export let config = {};
|
25 |
export let confidenceLabel = "";
|
@@ -31,15 +34,16 @@
|
|
31 |
detail,
|
32 |
}: CustomEvent<FileData | FileData[]>): Promise<void> {
|
33 |
value = detail;
|
|
|
|
|
34 |
await tick();
|
35 |
dispatch("change", value);
|
36 |
dispatch("upload", detail);
|
37 |
-
console.log("upload", detail);
|
38 |
}
|
39 |
|
40 |
function handle_clear(): void {
|
41 |
value = null;
|
42 |
-
|
43 |
dispatch("change", null);
|
44 |
dispatch("clear");
|
45 |
}
|
@@ -53,34 +57,23 @@
|
|
53 |
error: string;
|
54 |
}>();
|
55 |
|
56 |
-
let accept_file_types: string | null;
|
57 |
-
if (file_types == null) {
|
58 |
-
accept_file_types = null;
|
59 |
-
} else {
|
60 |
-
file_types = file_types.map((x) => {
|
61 |
-
if (x.startsWith(".")) {
|
62 |
-
return x;
|
63 |
-
}
|
64 |
-
return x + "/*";
|
65 |
-
});
|
66 |
-
accept_file_types = file_types.join(", ");
|
67 |
-
}
|
68 |
-
|
69 |
let dragging = false;
|
70 |
$: dispatch("drag", dragging);
|
71 |
</script>
|
72 |
|
73 |
-
<BlockLabel
|
74 |
-
{show_label}
|
75 |
-
Icon={File}
|
76 |
-
float={value === null}
|
77 |
-
label={label || "File"}
|
78 |
-
/>
|
79 |
|
80 |
-
{#if value}
|
81 |
<ModifyUpload {i18n} on:clear={handle_clear} absolute />
|
82 |
-
<FilePreview
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
{#if moldata != null && molviewer}
|
85 |
<MolecularViewer {moldata} {config} {confidenceLabel} {representations} />
|
86 |
{/if}
|
@@ -88,14 +81,19 @@
|
|
88 |
<FileRetrieval
|
89 |
{root}
|
90 |
on:load={handle_upload}
|
|
|
91 |
on:notfound={() => dispatch("notfound")}
|
92 |
/>
|
93 |
<Upload
|
94 |
on:load={handle_upload}
|
95 |
-
filetype={
|
96 |
{file_count}
|
|
|
97 |
{root}
|
98 |
bind:dragging
|
|
|
|
|
|
|
99 |
>
|
100 |
<slot />
|
101 |
</Upload>
|
|
|
1 |
<script lang="ts">
|
2 |
import { createEventDispatcher, tick } from "svelte";
|
3 |
import { Upload, ModifyUpload } from "@gradio/upload";
|
4 |
+
import type { FileData, Client } from "@gradio/client";
|
5 |
import { BlockLabel } from "@gradio/atoms";
|
6 |
import { File } from "@gradio/icons";
|
7 |
import FileRetrieval from "./FileRetrieval.svelte";
|
|
|
14 |
|
15 |
export let label: string;
|
16 |
export let show_label = true;
|
17 |
+
export let file_count: "single" | "multiple" | "directory" = "single";
|
18 |
export let file_types: string[] | null = null;
|
19 |
export let selectable = false;
|
20 |
export let root: string;
|
21 |
export let height: number | undefined = undefined;
|
22 |
export let i18n: I18nFormatter;
|
23 |
+
export let max_file_size: number | null = null;
|
24 |
+
export let upload: Client["upload"];
|
25 |
+
export let stream_handler: Client["stream"];
|
26 |
|
27 |
export let config = {};
|
28 |
export let confidenceLabel = "";
|
|
|
34 |
detail,
|
35 |
}: CustomEvent<FileData | FileData[]>): Promise<void> {
|
36 |
value = detail;
|
37 |
+
console.log("upload", detail);
|
38 |
+
|
39 |
await tick();
|
40 |
dispatch("change", value);
|
41 |
dispatch("upload", detail);
|
|
|
42 |
}
|
43 |
|
44 |
function handle_clear(): void {
|
45 |
value = null;
|
46 |
+
oldata = null;
|
47 |
dispatch("change", null);
|
48 |
dispatch("clear");
|
49 |
}
|
|
|
57 |
error: string;
|
58 |
}>();
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
let dragging = false;
|
61 |
$: dispatch("drag", dragging);
|
62 |
</script>
|
63 |
|
64 |
+
<BlockLabel {show_label} Icon={File} float={!value} label={label || "File"} />
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
+
{#if value && (Array.isArray(value) ? value.length > 0 : true)}
|
67 |
<ModifyUpload {i18n} on:clear={handle_clear} absolute />
|
68 |
+
<FilePreview
|
69 |
+
{i18n}
|
70 |
+
on:select
|
71 |
+
{selectable}
|
72 |
+
{value}
|
73 |
+
{height}
|
74 |
+
on:change
|
75 |
+
on:delete
|
76 |
+
/>
|
77 |
{#if moldata != null && molviewer}
|
78 |
<MolecularViewer {moldata} {config} {confidenceLabel} {representations} />
|
79 |
{/if}
|
|
|
81 |
<FileRetrieval
|
82 |
{root}
|
83 |
on:load={handle_upload}
|
84 |
+
{upload}
|
85 |
on:notfound={() => dispatch("notfound")}
|
86 |
/>
|
87 |
<Upload
|
88 |
on:load={handle_upload}
|
89 |
+
filetype={file_types}
|
90 |
{file_count}
|
91 |
+
{max_file_size}
|
92 |
{root}
|
93 |
bind:dragging
|
94 |
+
on:error
|
95 |
+
{stream_handler}
|
96 |
+
{upload}
|
97 |
>
|
98 |
<slot />
|
99 |
</Upload>
|
src/frontend/shared/MolecularViewer.svelte
CHANGED
@@ -1,21 +1,13 @@
|
|
1 |
<script lang="ts">
|
2 |
import * as mol from "3dmol/build/3Dmol.js";
|
3 |
-
let TDmol = mol
|
4 |
|
5 |
import { onMount, onDestroy } from "svelte";
|
6 |
|
7 |
-
// import RepresentationsIcon from "../static/RepresentationsIcon.svelte";
|
8 |
-
// import JSZip from "jszip";
|
9 |
-
// import { saveAs } from "file-saver";
|
10 |
-
|
11 |
let viewer;
|
12 |
export let confidenceLabel = null;
|
13 |
|
14 |
export let moldata = null;
|
15 |
-
// [
|
16 |
-
// { data: propdata, name: "Input", format: "pdb", asFrames: false },
|
17 |
-
// { data: moldata2, name: "Output", format: "pdb", asFrames: true },
|
18 |
-
// ];
|
19 |
|
20 |
let settings = {
|
21 |
backgroundColor: {
|
@@ -29,13 +21,11 @@
|
|
29 |
type: "toggle",
|
30 |
},
|
31 |
};
|
32 |
-
export let config = {
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
// disableFog: false,
|
38 |
-
// };
|
39 |
|
40 |
$: {
|
41 |
if (view != undefined) {
|
@@ -159,6 +149,7 @@
|
|
159 |
and: [selObj, { atom: ["N", "C", "O"], invert: true }],
|
160 |
};
|
161 |
}
|
|
|
162 |
if (rep.style === "surface") {
|
163 |
colorObj.opacity = 0.8;
|
164 |
view.addSurface(TDmol.SurfaceType.VDW, colorObj, selObj);
|
@@ -220,7 +211,7 @@
|
|
220 |
applyStyles(representations);
|
221 |
view.zoomTo();
|
222 |
view.render();
|
223 |
-
view.zoom(0.
|
224 |
|
225 |
representations.forEach((rep) => {
|
226 |
if (rep.color === "alphafold") {
|
|
|
1 |
<script lang="ts">
|
2 |
import * as mol from "3dmol/build/3Dmol.js";
|
3 |
+
let TDmol = mol;
|
4 |
|
5 |
import { onMount, onDestroy } from "svelte";
|
6 |
|
|
|
|
|
|
|
|
|
7 |
let viewer;
|
8 |
export let confidenceLabel = null;
|
9 |
|
10 |
export let moldata = null;
|
|
|
|
|
|
|
|
|
11 |
|
12 |
let settings = {
|
13 |
backgroundColor: {
|
|
|
21 |
type: "toggle",
|
22 |
},
|
23 |
};
|
24 |
+
export let config = {
|
25 |
+
backgroundColor: "white",
|
26 |
+
orthographic: false,
|
27 |
+
disableFog: false,
|
28 |
+
};
|
|
|
|
|
29 |
|
30 |
$: {
|
31 |
if (view != undefined) {
|
|
|
149 |
and: [selObj, { atom: ["N", "C", "O"], invert: true }],
|
150 |
};
|
151 |
}
|
152 |
+
|
153 |
if (rep.style === "surface") {
|
154 |
colorObj.opacity = 0.8;
|
155 |
view.addSurface(TDmol.SurfaceType.VDW, colorObj, selObj);
|
|
|
211 |
applyStyles(representations);
|
212 |
view.zoomTo();
|
213 |
view.render();
|
214 |
+
view.zoom(0.9, 100);
|
215 |
|
216 |
representations.forEach((rep) => {
|
217 |
if (rep.color === "alphafold") {
|
src/frontend/shared/utils.ts
CHANGED
@@ -10,32 +10,3 @@ export const prettyBytes = (bytes: number): string => {
|
|
10 |
let unit = units[i];
|
11 |
return bytes.toFixed(1) + " " + unit;
|
12 |
};
|
13 |
-
|
14 |
-
export const display_file_name = (value: FileData): string => {
|
15 |
-
var str: string;
|
16 |
-
str = value.orig_name;
|
17 |
-
const max_length = 30;
|
18 |
-
|
19 |
-
if (str.length > max_length) {
|
20 |
-
const truncated_name = str.substring(0, max_length);
|
21 |
-
const file_extension_index = str.lastIndexOf(".");
|
22 |
-
if (file_extension_index !== -1) {
|
23 |
-
const file_extension = str.slice(file_extension_index);
|
24 |
-
return `${truncated_name}..${file_extension}`;
|
25 |
-
}
|
26 |
-
return truncated_name;
|
27 |
-
}
|
28 |
-
return str;
|
29 |
-
};
|
30 |
-
|
31 |
-
export const display_file_size = (value: FileData | FileData[]): string => {
|
32 |
-
var total_size = 0;
|
33 |
-
if (Array.isArray(value)) {
|
34 |
-
for (var file of value) {
|
35 |
-
if (file.size !== undefined) total_size += file.size;
|
36 |
-
}
|
37 |
-
} else {
|
38 |
-
total_size = value.size || 0;
|
39 |
-
}
|
40 |
-
return prettyBytes(total_size);
|
41 |
-
};
|
|
|
10 |
let unit = units[i];
|
11 |
return bytes.toFixed(1) + " " + unit;
|
12 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/frontend/style.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
@import "tailwindcss";
|
src/pyproject.toml
CHANGED
@@ -8,12 +8,12 @@ build-backend = "hatchling.build"
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_molecule3d"
|
11 |
-
version = "0.0.
|
12 |
-
description = "
|
13 |
readme = "README.md"
|
14 |
-
license = "
|
15 |
requires-python = ">=3.8"
|
16 |
-
authors = [{ name = "
|
17 |
keywords = [
|
18 |
"machine learning",
|
19 |
"reproducibility",
|
@@ -24,10 +24,9 @@ keywords = [
|
|
24 |
"protein"
|
25 |
]
|
26 |
# Add dependencies here
|
27 |
-
dependencies = ["gradio>=4.0,<
|
28 |
classifiers = [
|
29 |
'Development Status :: 3 - Alpha',
|
30 |
-
'License :: OSI Approved :: Apache Software License',
|
31 |
'Operating System :: OS Independent',
|
32 |
'Programming Language :: Python :: 3',
|
33 |
'Programming Language :: Python :: 3 :: Only',
|
@@ -40,11 +39,12 @@ classifiers = [
|
|
40 |
'Topic :: Scientific/Engineering :: Visualization',
|
41 |
]
|
42 |
|
|
|
43 |
[project.optional-dependencies]
|
44 |
dev = ["build", "twine"]
|
45 |
|
46 |
[tool.hatch.build]
|
47 |
-
artifacts = ["/backend/gradio_molecule3d/templates", "*.pyi"
|
48 |
|
49 |
[tool.hatch.build.targets.wheel]
|
50 |
packages = ["/backend/gradio_molecule3d"]
|
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_molecule3d"
|
11 |
+
version = "0.0.6"
|
12 |
+
description = "Python library for easily interacting with trained machine learning models"
|
13 |
readme = "README.md"
|
14 |
+
license = "Apache-2.0"
|
15 |
requires-python = ">=3.8"
|
16 |
+
authors = [{ name = "YOUR NAME", email = "YOUREMAIL@domain.com" }]
|
17 |
keywords = [
|
18 |
"machine learning",
|
19 |
"reproducibility",
|
|
|
24 |
"protein"
|
25 |
]
|
26 |
# Add dependencies here
|
27 |
+
dependencies = ["gradio>=4.0,<6.0"]
|
28 |
classifiers = [
|
29 |
'Development Status :: 3 - Alpha',
|
|
|
30 |
'Operating System :: OS Independent',
|
31 |
'Programming Language :: Python :: 3',
|
32 |
'Programming Language :: Python :: 3 :: Only',
|
|
|
39 |
'Topic :: Scientific/Engineering :: Visualization',
|
40 |
]
|
41 |
|
42 |
+
|
43 |
[project.optional-dependencies]
|
44 |
dev = ["build", "twine"]
|
45 |
|
46 |
[tool.hatch.build]
|
47 |
+
artifacts = ["/backend/gradio_molecule3d/templates", "*.pyi"]
|
48 |
|
49 |
[tool.hatch.build.targets.wheel]
|
50 |
packages = ["/backend/gradio_molecule3d"]
|