##// END OF EJS Templates
add example notebook
Min RK -
Show More
@@ -0,0 +1,359 b''
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# Updatable Displays\n",
8 "\n",
9 "Note: This feature requires notebook >= 5.0 or JupyterLab, and \n",
10 "\n",
11 "\n",
12 "IPython 6 implements a new API as part of the Jupyter Protocol version 5.1 for easily updating displays.\n",
13 "\n",
14 "When you display something, you can now pass a `display_id` argument to attach an id to that output.\n",
15 "\n",
16 "Any future display with the same ID will also update other displays that had the same ID.\n",
17 "\n",
18 "`display` with a `display_id` will return a `DisplayHandle`\n",
19 "object, which gives you easy access to update the output:"
20 ]
21 },
22 {
23 "cell_type": "code",
24 "execution_count": 10,
25 "metadata": {
26 "collapsed": true
27 },
28 "outputs": [],
29 "source": [
30 "from IPython.display import display, update_display"
31 ]
32 },
33 {
34 "cell_type": "code",
35 "execution_count": 13,
36 "metadata": {},
37 "outputs": [
38 {
39 "data": {
40 "text/plain": [
41 "'z'"
42 ]
43 },
44 "metadata": {},
45 "output_type": "display_data"
46 },
47 {
48 "data": {
49 "text/plain": [
50 "<DisplayHandle display_id=update-me>"
51 ]
52 },
53 "execution_count": 13,
54 "metadata": {},
55 "output_type": "execute_result"
56 }
57 ],
58 "source": [
59 "handle = display('x', display_id='update-me')\n",
60 "handle"
61 ]
62 },
63 {
64 "cell_type": "markdown",
65 "metadata": {},
66 "source": [
67 "When we call `handle.display('y')`, we get a new display of 'y',\n",
68 "but in addition to that, we updated the previous display."
69 ]
70 },
71 {
72 "cell_type": "code",
73 "execution_count": 14,
74 "metadata": {},
75 "outputs": [
76 {
77 "data": {
78 "text/plain": [
79 "'z'"
80 ]
81 },
82 "metadata": {},
83 "output_type": "display_data"
84 }
85 ],
86 "source": [
87 "handle.display('y')"
88 ]
89 },
90 {
91 "cell_type": "markdown",
92 "metadata": {},
93 "source": [
94 "We can also *just* update the existing displays,\n",
95 "without creating a new display:"
96 ]
97 },
98 {
99 "cell_type": "code",
100 "execution_count": 15,
101 "metadata": {
102 "collapsed": true
103 },
104 "outputs": [],
105 "source": [
106 "handle.update('z')"
107 ]
108 },
109 {
110 "cell_type": "markdown",
111 "metadata": {},
112 "source": [
113 "You don't have to generate display_ids yourself,\n",
114 "if you specify `display_id=True`, then a unique ID will be assigned:"
115 ]
116 },
117 {
118 "cell_type": "code",
119 "execution_count": 16,
120 "metadata": {},
121 "outputs": [
122 {
123 "data": {
124 "text/plain": [
125 "'hello'"
126 ]
127 },
128 "metadata": {},
129 "output_type": "display_data"
130 },
131 {
132 "data": {
133 "text/plain": [
134 "<DisplayHandle display_id=07fc47b2ef652ccb70addeee3eb0981a>"
135 ]
136 },
137 "execution_count": 16,
138 "metadata": {},
139 "output_type": "execute_result"
140 }
141 ],
142 "source": [
143 "handle = display(\"hello\", display_id=True)\n",
144 "handle"
145 ]
146 },
147 {
148 "cell_type": "markdown",
149 "metadata": {},
150 "source": [
151 "Calling `handle.display(obj)` is the same as calling `display(obj, handle.display_id)`,\n",
152 "so you don't need to use the handle objects if you don't want to:"
153 ]
154 },
155 {
156 "cell_type": "code",
157 "execution_count": 17,
158 "metadata": {},
159 "outputs": [
160 {
161 "data": {
162 "text/plain": [
163 "'z'"
164 ]
165 },
166 "metadata": {},
167 "output_type": "display_data"
168 }
169 ],
170 "source": [
171 "display('x', display_id='here');"
172 ]
173 },
174 {
175 "cell_type": "code",
176 "execution_count": 18,
177 "metadata": {},
178 "outputs": [
179 {
180 "data": {
181 "text/plain": [
182 "'z'"
183 ]
184 },
185 "metadata": {},
186 "output_type": "display_data"
187 }
188 ],
189 "source": [
190 "display('y', display_id='here');"
191 ]
192 },
193 {
194 "cell_type": "markdown",
195 "metadata": {},
196 "source": [
197 "And just like `display`, there is now `update_display`,\n",
198 "which is what `DisplayHandle.update` calls:"
199 ]
200 },
201 {
202 "cell_type": "code",
203 "execution_count": 19,
204 "metadata": {
205 "collapsed": true
206 },
207 "outputs": [],
208 "source": [
209 "update_display('z', display_id='here')"
210 ]
211 },
212 {
213 "cell_type": "markdown",
214 "metadata": {},
215 "source": [
216 "## More detailed example\n",
217 "\n",
218 "One of the motivating use cases for this is simple progress bars.\n",
219 "\n",
220 "Here is an example ProgressBar using these APIs:"
221 ]
222 },
223 {
224 "cell_type": "code",
225 "execution_count": 35,
226 "metadata": {},
227 "outputs": [
228 {
229 "data": {
230 "text/html": [
231 "<progress\n",
232 " value=10\n",
233 " max=10\n",
234 " style=\"width: 60ex\"/>\n",
235 " 10 / 10\n",
236 " "
237 ],
238 "text/plain": [
239 "[============================================================] 10/10"
240 ]
241 },
242 "metadata": {},
243 "output_type": "display_data"
244 }
245 ],
246 "source": [
247 "import os\n",
248 "from binascii import hexlify\n",
249 "\n",
250 "class ProgressBar(object):\n",
251 " def __init__(self, capacity):\n",
252 " self.progress = 0\n",
253 " self.capacity = capacity\n",
254 " self.html_width = '60ex'\n",
255 " self.text_width = 60\n",
256 " self._display_id = hexlify(os.urandom(8)).decode('ascii')\n",
257 " \n",
258 " def __repr__(self):\n",
259 " fraction = self.progress / self.capacity\n",
260 " filled = '=' * int(fraction * self.text_width)\n",
261 " rest = ' ' * (self.text_width - len(filled))\n",
262 " return '[{}{}] {}/{}'.format(\n",
263 " filled, rest,\n",
264 " self.progress, self.capacity,\n",
265 " )\n",
266 " \n",
267 " def _repr_html_(self):\n",
268 " return \"\"\"<progress\n",
269 " value={progress}\n",
270 " max={capacity}\n",
271 " style=\"width: {width}\"/>\n",
272 " {progress} / {capacity}\n",
273 " \"\"\".format(\n",
274 " progress=self.progress,\n",
275 " capacity=self.capacity,\n",
276 " width=self.html_width,\n",
277 " )\n",
278 " \n",
279 " def display(self):\n",
280 " display(self, display_id=self._display_id)\n",
281 " \n",
282 " def update(self):\n",
283 " update_display(self, display_id=self._display_id)\n",
284 "\n",
285 "bar = ProgressBar(10)\n",
286 "bar.display()"
287 ]
288 },
289 {
290 "cell_type": "markdown",
291 "metadata": {},
292 "source": [
293 "And the ProgressBar has `.display` and `.update` methods:"
294 ]
295 },
296 {
297 "cell_type": "code",
298 "execution_count": 36,
299 "metadata": {},
300 "outputs": [
301 {
302 "data": {
303 "text/html": [
304 "<progress\n",
305 " value=10\n",
306 " max=10\n",
307 " style=\"width: 60ex\"/>\n",
308 " 10 / 10\n",
309 " "
310 ],
311 "text/plain": [
312 "[============================================================] 10/10"
313 ]
314 },
315 "metadata": {},
316 "output_type": "display_data"
317 }
318 ],
319 "source": [
320 "import time\n",
321 "\n",
322 "bar.display()\n",
323 "\n",
324 "for i in range(11):\n",
325 " bar.progress = i\n",
326 " bar.update()\n",
327 " time.sleep(0.25)"
328 ]
329 },
330 {
331 "cell_type": "markdown",
332 "metadata": {},
333 "source": [
334 "We would encourage any updatable-display objects that track their own display_ids to follow-suit with `.display()` and `.update()` or `.update_display()` methods."
335 ]
336 }
337 ],
338 "metadata": {
339 "kernelspec": {
340 "display_name": "Python 3",
341 "language": "python",
342 "name": "python3"
343 },
344 "language_info": {
345 "codemirror_mode": {
346 "name": "ipython",
347 "version": 3
348 },
349 "file_extension": ".py",
350 "mimetype": "text/x-python",
351 "name": "python",
352 "nbconvert_exporter": "python",
353 "pygments_lexer": "ipython3",
354 "version": "3.5.1"
355 }
356 },
357 "nbformat": 4,
358 "nbformat_minor": 1
359 }
General Comments 0
You need to be logged in to leave comments. Login now