treizh commited on
Commit
11eac02
·
verified ·
1 Parent(s): 5b32eee

Upload app.ipynb with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.ipynb +227 -37
app.ipynb CHANGED
@@ -32,11 +32,14 @@
32
  "source": [
33
  "from pathlib import Path\n",
34
  "from io import StringIO\n",
 
 
35
  "\n",
36
  "import pandas as pd\n",
37
  "import panel as pn\n",
38
  "\n",
39
- "import scripts.tap_const as tc"
 
40
  ]
41
  },
42
  {
@@ -52,11 +55,23 @@
52
  "metadata": {},
53
  "outputs": [],
54
  "source": [
55
- "pn.extension(\"plotly\", \"tabulator\")\n",
56
  "\n",
57
  "template = pn.template.BootstrapTemplate(title=\"Ralstonia Annotation Tool\")"
58
  ]
59
  },
 
 
 
 
 
 
 
 
 
 
 
 
60
  {
61
  "cell_type": "markdown",
62
  "metadata": {},
@@ -95,35 +110,21 @@
95
  "cell_type": "markdown",
96
  "metadata": {},
97
  "source": [
98
- "## Functions"
99
- ]
100
- },
101
- {
102
- "cell_type": "code",
103
- "execution_count": null,
104
- "metadata": {},
105
- "outputs": [],
106
- "source": [
107
- "def to_dataframe(value):\n",
108
- " if not value or not isinstance(value, bytes):\n",
109
- " return pd.DataFrame()\n",
110
- "\n",
111
- " string_io = StringIO(value.decode(\"utf8\"))\n",
112
- " return pd.read_csv(string_io, sep=\";\")"
113
  ]
114
  },
115
  {
116
  "cell_type": "markdown",
117
  "metadata": {},
118
  "source": [
119
- "## Source Selection"
120
  ]
121
  },
122
  {
123
  "cell_type": "markdown",
124
  "metadata": {},
125
  "source": [
126
- "### Download Template"
127
  ]
128
  },
129
  {
@@ -132,20 +133,19 @@
132
  "metadata": {},
133
  "outputs": [],
134
  "source": [
135
- "template_download = pn.widgets.FileDownload(\n",
136
  " file=pt_data.joinpath(f\"{EXPERIMENT}_raw.csv\"),\n",
137
  " filename=f\"{EXPERIMENT}_raw.csv\",\n",
138
  " button_type=\"success\",\n",
139
  " label=\"Download template annotation file\",\n",
140
- ")\n",
141
- "template_download"
142
  ]
143
  },
144
  {
145
  "cell_type": "markdown",
146
  "metadata": {},
147
  "source": [
148
- "### Upload existing file"
149
  ]
150
  },
151
  {
@@ -156,20 +156,47 @@
156
  "source": [
157
  "file_input = pn.widgets.FileInput(accept=\".csv,.json\")\n",
158
  "table = pn.widgets.Tabulator(\n",
159
- " pn.bind(to_dataframe, file_input),\n",
160
  " pagination=\"local\",\n",
161
  " page_size=20,\n",
162
  " sizing_mode=\"stretch_width\",\n",
163
  ")\n",
164
- "layout = pn.Column(file_input, table)\n",
165
- "layout"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  ]
167
  },
168
  {
169
  "cell_type": "markdown",
170
  "metadata": {},
171
  "source": [
172
- "## Annotation Tools"
173
  ]
174
  },
175
  {
@@ -179,16 +206,24 @@
179
  "outputs": [],
180
  "source": [
181
  "sl_plant = pn.widgets.Select(name=\"Plant\", options=[])\n",
182
- "@pn.depends(table.param.value, watch=True)\n",
183
- "def on_file_loaded(file):\n",
184
- " sl_plant.options = list(table.value.plant.unique())"
 
 
 
 
 
 
 
 
185
  ]
186
  },
187
  {
188
  "cell_type": "markdown",
189
  "metadata": {},
190
  "source": [
191
- "## Render"
192
  ]
193
  },
194
  {
@@ -197,14 +232,165 @@
197
  "metadata": {},
198
  "outputs": [],
199
  "source": [
200
- "template.sidebar.append(\n",
201
- " pn.Card(pn.Column(template_download, file_input), title=\"File Manager\"),\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  ")\n",
203
- "template.sidebar.append(sl_plant)\n",
204
  "\n",
205
- "template.main.append(table)\n",
206
  "\n",
207
- "template.servable()"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  ]
209
  },
210
  {
@@ -212,7 +398,11 @@
212
  "execution_count": null,
213
  "metadata": {},
214
  "outputs": [],
215
- "source": []
 
 
 
 
216
  }
217
  ],
218
  "metadata": {
 
32
  "source": [
33
  "from pathlib import Path\n",
34
  "from io import StringIO\n",
35
+ "import json\n",
36
+ "from datetime import datetime as dt\n",
37
  "\n",
38
  "import pandas as pd\n",
39
  "import panel as pn\n",
40
  "\n",
41
+ "import scripts.tap_const as tc\n",
42
+ "import scripts.tap_image as ti"
43
  ]
44
  },
45
  {
 
55
  "metadata": {},
56
  "outputs": [],
57
  "source": [
58
+ "pn.extension(\"tabulator\", design=\"bootstrap\")\n",
59
  "\n",
60
  "template = pn.template.BootstrapTemplate(title=\"Ralstonia Annotation Tool\")"
61
  ]
62
  },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {},
67
+ "outputs": [],
68
+ "source": [
69
+ "pd.set_option(\"display.max_colwidth\", 500)\n",
70
+ "pd.set_option(\"display.max_columns\", 500)\n",
71
+ "pd.set_option(\"display.width\", 1000)\n",
72
+ "pd.set_option(\"display.max_rows\", 20)"
73
+ ]
74
+ },
75
  {
76
  "cell_type": "markdown",
77
  "metadata": {},
 
110
  "cell_type": "markdown",
111
  "metadata": {},
112
  "source": [
113
+ "## User Interface"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  ]
115
  },
116
  {
117
  "cell_type": "markdown",
118
  "metadata": {},
119
  "source": [
120
+ "### Source Selection"
121
  ]
122
  },
123
  {
124
  "cell_type": "markdown",
125
  "metadata": {},
126
  "source": [
127
+ "#### Download Template"
128
  ]
129
  },
130
  {
 
133
  "metadata": {},
134
  "outputs": [],
135
  "source": [
136
+ "dwn_template = pn.widgets.FileDownload(\n",
137
  " file=pt_data.joinpath(f\"{EXPERIMENT}_raw.csv\"),\n",
138
  " filename=f\"{EXPERIMENT}_raw.csv\",\n",
139
  " button_type=\"success\",\n",
140
  " label=\"Download template annotation file\",\n",
141
+ ")"
 
142
  ]
143
  },
144
  {
145
  "cell_type": "markdown",
146
  "metadata": {},
147
  "source": [
148
+ "#### Upload existing file"
149
  ]
150
  },
151
  {
 
156
  "source": [
157
  "file_input = pn.widgets.FileInput(accept=\".csv,.json\")\n",
158
  "table = pn.widgets.Tabulator(\n",
159
+ " value=pd.DataFrame(),\n",
160
  " pagination=\"local\",\n",
161
  " page_size=20,\n",
162
  " sizing_mode=\"stretch_width\",\n",
163
  ")\n",
164
+ "\n",
165
+ "ck_show_finished = pn.widgets.ToggleIcon(\n",
166
+ " icon=\"eye-x\", size=\"4em\", active_icon=\"eye\", value=False\n",
167
+ ")\n",
168
+ "mk_show_finished = pn.pane.Markdown(\"Hide complete plants\")\n",
169
+ "\n",
170
+ "@pn.depends(file_input.param.value, watch=True)\n",
171
+ "def on_file_loaded(value):\n",
172
+ " if not value or not isinstance(value, bytes):\n",
173
+ " return pd.DataFrame()\n",
174
+ "\n",
175
+ " string_io = StringIO(value.decode(\"utf8\"))\n",
176
+ " ret = pd.read_csv(string_io, sep=\";\").assign(\n",
177
+ " file_name=lambda x: x.filepath.str.replace(\".tif\", \".jpg\")\n",
178
+ " )\n",
179
+ " ret = ret[ret.treatment == \"RS\"]\n",
180
+ " if \"di\" not in ret:\n",
181
+ " ret[\"di\"] = 0\n",
182
+ " if \"done\" not in ret:\n",
183
+ " ret[\"done\"] = False\n",
184
+ "\n",
185
+ " table.value = ret"
186
+ ]
187
+ },
188
+ {
189
+ "cell_type": "markdown",
190
+ "metadata": {},
191
+ "source": [
192
+ "### Annotation Tools"
193
  ]
194
  },
195
  {
196
  "cell_type": "markdown",
197
  "metadata": {},
198
  "source": [
199
+ "#### Plant Selection"
200
  ]
201
  },
202
  {
 
206
  "outputs": [],
207
  "source": [
208
  "sl_plant = pn.widgets.Select(name=\"Plant\", options=[])\n",
209
+ "\n",
210
+ "@pn.depends(table.param.value, ck_show_finished.param.value, watch=True)\n",
211
+ "def on_table_changed(file: str, show_done: bool):\n",
212
+ " df = table.value\n",
213
+ " if \"done\" in df:\n",
214
+ " sl_plant.options = list(\n",
215
+ " df.plant.unique() if show_done is True else df[df.done == False].plant.unique()\n",
216
+ " )\n",
217
+ " mk_show_finished.object = (\n",
218
+ " \"Show complete plants\" if show_done is True else \"Hide complete plants\"\n",
219
+ " )"
220
  ]
221
  },
222
  {
223
  "cell_type": "markdown",
224
  "metadata": {},
225
  "source": [
226
+ "#### Main Annotation UI"
227
  ]
228
  },
229
  {
 
232
  "metadata": {},
233
  "outputs": [],
234
  "source": [
235
+ "im_current = pn.pane.Image(max_width=800, max_height=800, sizing_mode=\"stretch_width\")\n",
236
+ "discrete_player = pn.widgets.DiscretePlayer(\n",
237
+ " name=\"Discrete Player\", options=[0], value=0, loop_policy=\"loop\"\n",
238
+ ")\n",
239
+ "discrete_player.interval = 1000\n",
240
+ "ii_disease_index = pn.widgets.IntInput(\n",
241
+ " name=\"Disease Index\",\n",
242
+ " start=0,\n",
243
+ " end=4,\n",
244
+ " step=1,\n",
245
+ " value=0,\n",
246
+ " max_width=80,\n",
247
+ " sizing_mode=\"stretch_width\",\n",
248
+ ")\n",
249
+ "\n",
250
+ "dwn_annotations = pn.widgets.FileDownload(\n",
251
+ " file=pt_data.joinpath(f\"{EXPERIMENT}_raw.csv\"),\n",
252
+ " filename=f\"{EXPERIMENT}_raw.csv\",\n",
253
+ " label=\" \",\n",
254
+ " name=\"Download Annotations\",\n",
255
+ " sizing_mode=\"stretch_width\",\n",
256
+ " icon=\"file-download\",\n",
257
+ " button_type=\"primary\",\n",
258
  ")\n",
 
259
  "\n",
260
+ "updating: bool = False\n",
261
  "\n",
262
+ "\n",
263
+ "@pn.cache(max_items=10, policy=\"LRU\")\n",
264
+ "def get_plant_data(df, plant_name) -> pd.DataFrame:\n",
265
+ " file_names, rotations = [], []\n",
266
+ " for k, v in json.load(\n",
267
+ " open(pt_rotations.joinpath(sl_plant.value).with_suffix(\".json\"), \"r\")\n",
268
+ " ).items():\n",
269
+ " file_names.append(k + \".jpg\")\n",
270
+ " rotations.append(v)\n",
271
+ "\n",
272
+ " return df[df.plant == plant_name].merge(\n",
273
+ " pd.DataFrame(data={\"file_name\": file_names, \"rotation\": rotations}),\n",
274
+ " on=\"file_name\",\n",
275
+ " how=\"left\",\n",
276
+ " )\n",
277
+ "\n",
278
+ "\n",
279
+ "def update_image():\n",
280
+ " global updating\n",
281
+ " updating = True\n",
282
+ " try:\n",
283
+ " row = (\n",
284
+ " get_plant_data(df=table.value, plant_name=sl_plant.value)\n",
285
+ " .set_index(\"job_id\")\n",
286
+ " .loc[discrete_player.value]\n",
287
+ " )\n",
288
+ " if pt_images.joinpath(row.file_name).is_file() is True:\n",
289
+ " im_current.object = ti.to_pil(\n",
290
+ " ti.rotate_image(\n",
291
+ " image=ti.load_image(file_name=row.file_name, file_path=pt_images),\n",
292
+ " angle=row.rotation,\n",
293
+ " )\n",
294
+ " )\n",
295
+ " ii_disease_index.value = row.di\n",
296
+ " else:\n",
297
+ " im_current.object = None\n",
298
+ " finally:\n",
299
+ " updating = False\n",
300
+ "\n",
301
+ "\n",
302
+ "@pn.depends(sl_plant.param.value, watch=True)\n",
303
+ "def on_plant_changed(plant_name):\n",
304
+ " discrete_player.options = get_plant_data(\n",
305
+ " df=table.value, plant_name=plant_name\n",
306
+ " ).job_id.to_list()\n",
307
+ " discrete_player.value = discrete_player.options[0]\n",
308
+ " update_image()\n",
309
+ "\n",
310
+ "\n",
311
+ "@pn.depends(discrete_player.param.value, watch=True)\n",
312
+ "def on_index_changed(index):\n",
313
+ " update_image()\n",
314
+ "\n",
315
+ "\n",
316
+ "@pn.depends(ii_disease_index.param.value, watch=True)\n",
317
+ "def on_di_changed(di):\n",
318
+ " if updating is True:\n",
319
+ " return\n",
320
+ " table.value.loc[\n",
321
+ " (table.value.plant == sl_plant.value)\n",
322
+ " & (table.value.job_id >= discrete_player.value),\n",
323
+ " \"di\",\n",
324
+ " ] = di\n",
325
+ " table.value.loc[(table.value.plant == sl_plant.value), \"done\"] = True\n",
326
+ "\n",
327
+ " s_buf = StringIO()\n",
328
+ " table.value.to_csv(s_buf, sep=\";\")\n",
329
+ " s_buf.seek(0)\n",
330
+ " dwn_annotations.filename = f\"{EXPERIMENT}_{dt.now().strftime('%Y%d%m_%H%M%S')}.csv\"\n",
331
+ " dwn_annotations.label = \"Download\"\n",
332
+ " dwn_annotations.file = s_buf\n",
333
+ " dwn_annotations.icon = \"file-download\""
334
+ ]
335
+ },
336
+ {
337
+ "cell_type": "markdown",
338
+ "metadata": {},
339
+ "source": [
340
+ "### Build Components"
341
+ ]
342
+ },
343
+ {
344
+ "cell_type": "code",
345
+ "execution_count": null,
346
+ "metadata": {},
347
+ "outputs": [],
348
+ "source": [
349
+ "sidebar = pn.Column(\n",
350
+ " pn.Card(pn.Column(dwn_template, file_input), title=\"File Manager\"),\n",
351
+ " sl_plant,\n",
352
+ " pn.Row(\n",
353
+ " ck_show_finished,\n",
354
+ " pn.Column(pn.layout.VSpacer(), mk_show_finished, pn.layout.VSpacer()),\n",
355
+ " height=50,\n",
356
+ " ),\n",
357
+ ")\n",
358
+ "main = pn.Column(\n",
359
+ " im_current,\n",
360
+ " pn.Row(\n",
361
+ " # pn.layout.HSpacer(),\n",
362
+ " discrete_player,\n",
363
+ " ii_disease_index,\n",
364
+ " dwn_annotations,\n",
365
+ " # pn.layout.HSpacer(),\n",
366
+ " ),\n",
367
+ " max_width=800,\n",
368
+ " max_height=800,\n",
369
+ " sizing_mode=\"stretch_width\",\n",
370
+ ")"
371
+ ]
372
+ },
373
+ {
374
+ "cell_type": "markdown",
375
+ "metadata": {},
376
+ "source": [
377
+ "### Test"
378
+ ]
379
+ },
380
+ {
381
+ "cell_type": "code",
382
+ "execution_count": null,
383
+ "metadata": {},
384
+ "outputs": [],
385
+ "source": [
386
+ "pn.Row(sidebar, main)"
387
+ ]
388
+ },
389
+ {
390
+ "cell_type": "markdown",
391
+ "metadata": {},
392
+ "source": [
393
+ "## Render"
394
  ]
395
  },
396
  {
 
398
  "execution_count": null,
399
  "metadata": {},
400
  "outputs": [],
401
+ "source": [
402
+ "template.sidebar.append(sidebar)\n",
403
+ "template.main.append(main)\n",
404
+ "template.servable()"
405
+ ]
406
  }
407
  ],
408
  "metadata": {