Browse code

update pre-commit filter versions

Bas Nijholt authored on 07/08/2020 13:31:33
Showing 1 changed files
... ...
@@ -64,8 +64,8 @@ def ensure_plotly():
64 64
         import plotly
65 65
 
66 66
         if not _plotly_enabled:
67
-            import plotly.graph_objs
68 67
             import plotly.figure_factory
68
+            import plotly.graph_objs
69 69
             import plotly.offline
70 70
 
71 71
             # This injects javascript and should happen only once
Browse code

join strings

Bas Nijholt authored on 12/05/2020 15:34:25
Showing 1 changed files
... ...
@@ -31,7 +31,7 @@ def notebook_extension(*, _inline_js=True):
31 31
             _holoviews_enabled = True
32 32
     except ModuleNotFoundError:
33 33
         warnings.warn(
34
-            "holoviews is not installed; plotting " "is disabled.", RuntimeWarning
34
+            "holoviews is not installed; plotting is disabled.", RuntimeWarning
35 35
         )
36 36
 
37 37
     # Load ipywidgets
... ...
@@ -42,7 +42,7 @@ def notebook_extension(*, _inline_js=True):
42 42
             _ipywidgets_enabled = True
43 43
     except ModuleNotFoundError:
44 44
         warnings.warn(
45
-            "ipywidgets is not installed; live_info " "is disabled.", RuntimeWarning
45
+            "ipywidgets is not installed; live_info is disabled.", RuntimeWarning
46 46
         )
47 47
 
48 48
     # Enable asyncio integration
Browse code

simplify _table_row in notebook_integration.py

Bas Nijholt authored on 19/12/2019 09:39:59
Showing 1 changed files
... ...
@@ -233,11 +233,10 @@ def live_info(runner, *, update_interval=0.5):
233 233
 
234 234
 def _table_row(i, key, value):
235 235
     """Style the rows of a table. Based on the default Jupyterlab table style."""
236
-    style_odd = "text-align: right; padding: 0.5em 0.5em; line-height: 1.0;"
237
-    style_even = style_odd + "background: var(--md-grey-100);"
238
-    template = '<tr><th style="{style}">{key}</th><th style="{style}">{value}</th></tr>'
239
-    style = style_odd if i % 2 == 1 else style_even
240
-    return template.format(style=style, key=key, value=value)
236
+    style = "text-align: right; padding: 0.5em 0.5em; line-height: 1.0;"
237
+    if i % 2 == 1:
238
+        style += " background: var(--md-grey-100);"
239
+    return f'<tr><th style="{style}">{key}</th><th style="{style}">{value}</th></tr>'
241 240
 
242 241
 
243 242
 def _info_html(runner):
Browse code

color the overhead between red and green (#252)

color the overhead between red and green

Bas Nijholt authored on 18/12/2019 18:26:30 • Joseph Weston committed on 18/12/2019 18:26:30
Showing 1 changed files
... ...
@@ -250,10 +250,14 @@ def _info_html(runner):
250 250
         "finished": "green",
251 251
     }[status]
252 252
 
253
+    overhead = runner.overhead()
254
+    red_level = max(0, min(int(255 * overhead / 100), 255))
255
+    overhead_color = "#{:02x}{:02x}{:02x}".format(red_level, 255 - red_level, 0)
256
+
253 257
     info = [
254 258
         ("status", f'<font color="{color}">{status}</font>'),
255 259
         ("elapsed time", datetime.timedelta(seconds=runner.elapsed_time())),
256
-        ("overhead", f"{runner.overhead():.2f}%"),
260
+        ("overhead", f'<font color="{overhead_color}">{overhead:.2f}%</font>'),
257 261
     ]
258 262
 
259 263
     with suppress(Exception):
Browse code

improve the style of the live_info widget, closes #250 (#251)

Based on the default style of the Jupyterlab table.

Bas Nijholt authored on 18/12/2019 17:36:23 • GitHub committed on 18/12/2019 17:36:23
Showing 1 changed files
... ...
@@ -228,14 +228,16 @@ def live_info(runner, *, update_interval=0.5):
228 228
 
229 229
     runner.ioloop.create_task(update())
230 230
 
231
-    display(
232
-        ipywidgets.HBox(
233
-            (status, cancel),
234
-            layout=ipywidgets.Layout(
235
-                border="solid 1px", width="200px", align_items="center"
236
-            ),
237
-        )
238
-    )
231
+    display(ipywidgets.VBox((status, cancel)))
232
+
233
+
234
+def _table_row(i, key, value):
235
+    """Style the rows of a table. Based on the default Jupyterlab table style."""
236
+    style_odd = "text-align: right; padding: 0.5em 0.5em; line-height: 1.0;"
237
+    style_even = style_odd + "background: var(--md-grey-100);"
238
+    template = '<tr><th style="{style}">{key}</th><th style="{style}">{value}</th></tr>'
239
+    style = style_odd if i % 2 == 1 else style_even
240
+    return template.format(style=style, key=key, value=value)
239 241
 
240 242
 
241 243
 def _info_html(runner):
... ...
@@ -260,11 +262,10 @@ def _info_html(runner):
260 262
     with suppress(Exception):
261 263
         info.append(("latest loss", f'{runner.learner._cache["loss"]:.3f}'))
262 264
 
263
-    template = '<dt class="ignore-css">{}</dt><dd>{}</dd>'
264
-    table = "\n".join(template.format(k, v) for k, v in info)
265
+    table = "\n".join(_table_row(i, k, v) for i, (k, v) in enumerate(info))
265 266
 
266 267
     return f"""
267
-        <dl>
268
+        <table>
268 269
         {table}
269
-        </dl>
270
+        </table>
270 271
     """
Browse code

run pre-commit run --all

Bas Nijholt authored on 11/12/2019 14:00:39
Showing 1 changed files
... ...
@@ -1,5 +1,3 @@
1
-# -*- coding: utf-8 -*-
2
-
3 1
 import asyncio
4 2
 import datetime
5 3
 import importlib
Browse code

set the DynamicMap.cache_size = 1

Bas Nijholt authored on 24/05/2019 20:33:30
Showing 1 changed files
... ...
@@ -136,6 +136,7 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None, normalize=T
136 136
 
137 137
     streams = [hv.streams.Stream.define("Next")()]
138 138
     dm = hv.DynamicMap(plot_generator(), streams=streams)
139
+    dm.cache_size = 1
139 140
 
140 141
     if normalize:
141 142
         # XXX: change when https://github.com/pyviz/holoviews/issues/3637
Browse code

make the 'normalize' argument available in 'runner.live_plot'

Bas Nijholt authored on 15/05/2019 21:02:12
Showing 1 changed files
... ...
@@ -96,7 +96,7 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None, normalize=T
96 96
 
97 97
     Parameters
98 98
     ----------
99
-    runner : `Runner`
99
+    runner : `~adaptive.Runner`
100 100
     plotter : function
101 101
         A function that takes the learner as a argument and returns a
102 102
         holoviews object. By default ``learner.plot()`` will be called.
Browse code

fix all flake8 issues and run pre-commit filters

Bas Nijholt authored on 08/05/2019 02:26:15
Showing 1 changed files
... ...
@@ -16,8 +16,10 @@ _plotly_enabled = False
16 16
 def notebook_extension(*, _inline_js=True):
17 17
     """Enable ipywidgets, holoviews, and asyncio notebook integration."""
18 18
     if not in_ipynb():
19
-        raise RuntimeError('"adaptive.notebook_extension()" may only be run '
20
-                           'from a Jupyter notebook.')
19
+        raise RuntimeError(
20
+            '"adaptive.notebook_extension()" may only be run '
21
+            "from a Jupyter notebook."
22
+        )
21 23
 
22 24
     global _async_enabled, _holoviews_enabled, _ipywidgets_enabled
23 25
 
... ...
@@ -26,54 +28,60 @@ def notebook_extension(*, _inline_js=True):
26 28
         _holoviews_enabled = False  # After closing a notebook the js is gone
27 29
         if not _holoviews_enabled:
28 30
             import holoviews
29
-            holoviews.notebook_extension('bokeh', logo=False, inline=_inline_js)
31
+
32
+            holoviews.notebook_extension("bokeh", logo=False, inline=_inline_js)
30 33
             _holoviews_enabled = True
31 34
     except ModuleNotFoundError:
32
-        warnings.warn("holoviews is not installed; plotting "
33
-                      "is disabled.", RuntimeWarning)
35
+        warnings.warn(
36
+            "holoviews is not installed; plotting " "is disabled.", RuntimeWarning
37
+        )
34 38
 
35 39
     # Load ipywidgets
36 40
     try:
37 41
         if not _ipywidgets_enabled:
38
-            import ipywidgets
42
+            import ipywidgets  # noqa: F401
43
+
39 44
             _ipywidgets_enabled = True
40 45
     except ModuleNotFoundError:
41
-        warnings.warn("ipywidgets is not installed; live_info "
42
-                      "is disabled.", RuntimeWarning)
46
+        warnings.warn(
47
+            "ipywidgets is not installed; live_info " "is disabled.", RuntimeWarning
48
+        )
43 49
 
44 50
     # Enable asyncio integration
45 51
     if not _async_enabled:
46
-        get_ipython().magic('gui asyncio')
52
+        get_ipython().magic("gui asyncio")  # noqa: F821
47 53
         _async_enabled = True
48 54
 
49 55
 
50 56
 def ensure_holoviews():
51 57
     try:
52
-        return importlib.import_module('holoviews')
58
+        return importlib.import_module("holoviews")
53 59
     except ModuleNotFoundError:
54
-        raise RuntimeError('holoviews is not installed; plotting is disabled.')
60
+        raise RuntimeError("holoviews is not installed; plotting is disabled.")
55 61
 
56 62
 
57 63
 def ensure_plotly():
58 64
     global _plotly_enabled
59 65
     try:
60 66
         import plotly
67
+
61 68
         if not _plotly_enabled:
62 69
             import plotly.graph_objs
63 70
             import plotly.figure_factory
64 71
             import plotly.offline
72
+
65 73
             # This injects javascript and should happen only once
66 74
             plotly.offline.init_notebook_mode()
67 75
             _plotly_enabled = True
68 76
         return plotly
69 77
     except ModuleNotFoundError:
70
-        raise RuntimeError('plotly is not installed; plotting is disabled.')
78
+        raise RuntimeError("plotly is not installed; plotting is disabled.")
71 79
 
72 80
 
73 81
 def in_ipynb():
74 82
     try:
75 83
         # If we are running in IPython, then `get_ipython()` is always a global
76
-        return get_ipython().__class__.__name__ == 'ZMQInteractiveShell'
84
+        return get_ipython().__class__.__name__ == "ZMQInteractiveShell"
77 85
     except NameError:
78 86
         return False
79 87
 
... ...
@@ -83,8 +91,7 @@ def in_ipynb():
83 91
 active_plotting_tasks = dict()
84 92
 
85 93
 
86
-def live_plot(runner, *, plotter=None, update_interval=2,
87
-              name=None, normalize=True):
94
+def live_plot(runner, *, plotter=None, update_interval=2, name=None, normalize=True):
88 95
     """Live plotting of the learner's data.
89 96
 
90 97
     Parameters
... ...
@@ -135,14 +142,17 @@ def live_plot(runner, *, plotter=None, update_interval=2,
135 142
         # is fixed.
136 143
         dm = dm.map(lambda obj: obj.opts(framewise=True), hv.Element)
137 144
 
138
-    cancel_button = ipywidgets.Button(description='cancel live-plot',
139
-                                      layout=ipywidgets.Layout(width='150px'))
145
+    cancel_button = ipywidgets.Button(
146
+        description="cancel live-plot", layout=ipywidgets.Layout(width="150px")
147
+    )
140 148
 
141 149
     # Could have used dm.periodic in the following, but this would either spin
142 150
     # off a thread (and learner is not threadsafe) or block the kernel.
143 151
 
144 152
     async def updater():
145
-        event = lambda: hv.streams.Stream.trigger(dm.streams) # XXX: used to be dm.event()
153
+        event = lambda: hv.streams.Stream.trigger(  # noqa: E731
154
+            dm.streams
155
+        )  # XXX: used to be dm.event()
146 156
         # see https://github.com/pyviz/holoviews/issues/3564
147 157
         try:
148 158
             while not runner.task.done():
... ...
@@ -152,7 +162,7 @@ def live_plot(runner, *, plotter=None, update_interval=2,
152 162
         finally:
153 163
             if active_plotting_tasks[name] is asyncio.Task.current_task():
154 164
                 active_plotting_tasks.pop(name, None)
155
-            cancel_button.layout.display = 'none'  # remove cancel button
165
+            cancel_button.layout.display = "none"  # remove cancel button
156 166
 
157 167
     def cancel(_):
158 168
         with suppress(KeyError):
... ...
@@ -177,7 +187,7 @@ def should_update(status):
177 187
         # i.e. we're offline for 12h, with an update_interval of 0.5s,
178 188
         # and without the reduced probability, we have buffer_size=86400.
179 189
         # With the correction this is np.log(86400) / np.log(1.1) = 119.2
180
-        return 1.1**buffer_size * random.random() < 1
190
+        return 1.1 ** buffer_size * random.random() < 1
181 191
     except Exception:
182 192
         # We catch any Exception because we are using a private API.
183 193
         return True
... ...
@@ -190,16 +200,19 @@ def live_info(runner, *, update_interval=0.5):
190 200
     visualized in a Jupyter notebook.
191 201
     """
192 202
     if not _holoviews_enabled:
193
-        raise RuntimeError("Live plotting is not enabled; did you run "
194
-                           "'adaptive.notebook_extension()'?")
203
+        raise RuntimeError(
204
+            "Live plotting is not enabled; did you run "
205
+            "'adaptive.notebook_extension()'?"
206
+        )
195 207
 
196 208
     import ipywidgets
197 209
     from IPython.display import display
198 210
 
199 211
     status = ipywidgets.HTML(value=_info_html(runner))
200 212
 
201
-    cancel = ipywidgets.Button(description='cancel runner',
202
-                               layout=ipywidgets.Layout(width='100px'))
213
+    cancel = ipywidgets.Button(
214
+        description="cancel runner", layout=ipywidgets.Layout(width="100px")
215
+    )
203 216
     cancel.on_click(lambda _: runner.cancel())
204 217
 
205 218
     async def update():
... ...
@@ -212,43 +225,47 @@ def live_info(runner, *, update_interval=0.5):
212 225
                 await asyncio.sleep(0.05)
213 226
 
214 227
         status.value = _info_html(runner)
215
-        cancel.layout.display = 'none'
228
+        cancel.layout.display = "none"
216 229
 
217 230
     runner.ioloop.create_task(update())
218 231
 
219
-    display(ipywidgets.HBox(
220
-        (status, cancel),
221
-        layout=ipywidgets.Layout(border='solid 1px',
222
-                                 width='200px',
223
-                                 align_items='center'),
224
-    ))
232
+    display(
233
+        ipywidgets.HBox(
234
+            (status, cancel),
235
+            layout=ipywidgets.Layout(
236
+                border="solid 1px", width="200px", align_items="center"
237
+            ),
238
+        )
239
+    )
225 240
 
226 241
 
227 242
 def _info_html(runner):
228 243
     status = runner.status()
229 244
 
230
-    color = {'cancelled': 'orange',
231
-             'failed': 'red',
232
-             'running': 'blue',
233
-             'finished': 'green'}[status]
245
+    color = {
246
+        "cancelled": "orange",
247
+        "failed": "red",
248
+        "running": "blue",
249
+        "finished": "green",
250
+    }[status]
234 251
 
235 252
     info = [
236
-        ('status', f'<font color="{color}">{status}</font>'),
237
-        ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
238
-        ('overhead', f'{runner.overhead():.2f}%'),
253
+        ("status", f'<font color="{color}">{status}</font>'),
254
+        ("elapsed time", datetime.timedelta(seconds=runner.elapsed_time())),
255
+        ("overhead", f"{runner.overhead():.2f}%"),
239 256
     ]
240 257
 
241 258
     with suppress(Exception):
242
-        info.append(('# of points', runner.learner.npoints))
259
+        info.append(("# of points", runner.learner.npoints))
243 260
 
244 261
     with suppress(Exception):
245
-        info.append(('latest loss', f'{runner.learner._cache["loss"]:.3f}'))
262
+        info.append(("latest loss", f'{runner.learner._cache["loss"]:.3f}'))
246 263
 
247 264
     template = '<dt class="ignore-css">{}</dt><dd>{}</dd>'
248
-    table = '\n'.join(template.format(k, v) for k, v in info)
265
+    table = "\n".join(template.format(k, v) for k, v in info)
249 266
 
250
-    return f'''
267
+    return f"""
251 268
         <dl>
252 269
         {table}
253 270
         </dl>
254
-    '''
271
+    """
Browse code

fix variable typo

Bas Nijholt authored on 08/05/2019 01:31:00
Showing 1 changed files
... ...
@@ -127,7 +127,7 @@ def live_plot(runner, *, plotter=None, update_interval=2,
127 127
             else:
128 128
                 yield plotter(runner.learner)
129 129
 
130
-    steams = [hv.streams.Stream.define("Next")()]
130
+    streams = [hv.streams.Stream.define("Next")()]
131 131
     dm = hv.DynamicMap(plot_generator(), streams=streams)
132 132
 
133 133
     if normalize:
Browse code

fix import order and style

Bas Nijholt authored on 07/05/2019 23:42:40
Showing 1 changed files
... ...
@@ -1,12 +1,11 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3 3
 import asyncio
4
-from contextlib import suppress
5 4
 import datetime
6 5
 import importlib
7 6
 import random
8 7
 import warnings
9
-
8
+from contextlib import suppress
10 9
 
11 10
 _async_enabled = False
12 11
 _holoviews_enabled = False
Browse code

add to-do and link holoviews issue

see https://github.com/pyviz/holoviews/issues/3637

Bas Nijholt authored on 25/04/2019 23:07:57
Showing 1 changed files
... ...
@@ -132,6 +132,8 @@ def live_plot(runner, *, plotter=None, update_interval=2,
132 132
     dm = hv.DynamicMap(plot_generator(), streams=streams)
133 133
 
134 134
     if normalize:
135
+        # XXX: change when https://github.com/pyviz/holoviews/issues/3637
136
+        # is fixed.
135 137
         dm = dm.map(lambda obj: obj.opts(framewise=True), hv.Element)
136 138
 
137 139
     cancel_button = ipywidgets.Button(description='cancel live-plot',
Browse code

renormalize the plots value axis on every update

Bas Nijholt authored on 19/04/2019 01:31:13
Showing 1 changed files
... ...
@@ -84,7 +84,8 @@ def in_ipynb():
84 84
 active_plotting_tasks = dict()
85 85
 
86 86
 
87
-def live_plot(runner, *, plotter=None, update_interval=2, name=None):
87
+def live_plot(runner, *, plotter=None, update_interval=2,
88
+              name=None, normalize=True):
88 89
     """Live plotting of the learner's data.
89 90
 
90 91
     Parameters
... ...
@@ -99,6 +100,8 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
99 100
         Name for the `live_plot` task in `adaptive.active_plotting_tasks`.
100 101
         By default the name is None and if another task with the same name
101 102
         already exists that other `live_plot` is canceled.
103
+    normalize : bool
104
+        Normalize (scale to fit) the frame upon each update.
102 105
 
103 106
     Returns
104 107
     -------
... ...
@@ -106,8 +109,10 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
106 109
         The plot that automatically updates every `update_interval`.
107 110
     """
108 111
     if not _holoviews_enabled:
109
-        raise RuntimeError("Live plotting is not enabled; did you run "
110
-                           "'adaptive.notebook_extension()'?")
112
+        raise RuntimeError(
113
+            "Live plotting is not enabled; did you run "
114
+            "'adaptive.notebook_extension()'?"
115
+        )
111 116
 
112 117
     import holoviews as hv
113 118
     import ipywidgets
... ...
@@ -123,8 +128,12 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
123 128
             else:
124 129
                 yield plotter(runner.learner)
125 130
 
126
-    dm = hv.DynamicMap(plot_generator(),
127
-                       streams=[hv.streams.Stream.define('Next')()])
131
+    steams = [hv.streams.Stream.define("Next")()]
132
+    dm = hv.DynamicMap(plot_generator(), streams=streams)
133
+
134
+    if normalize:
135
+        dm = dm.map(lambda obj: obj.opts(framewise=True), hv.Element)
136
+
128 137
     cancel_button = ipywidgets.Button(description='cancel live-plot',
129 138
                                       layout=ipywidgets.Layout(width='150px'))
130 139
 
Browse code

do not inline the HoloViews JS

Bas Nijholt authored on 26/03/2019 12:44:31
Showing 1 changed files
... ...
@@ -14,7 +14,7 @@ _ipywidgets_enabled = False
14 14
 _plotly_enabled = False
15 15
 
16 16
 
17
-def notebook_extension():
17
+def notebook_extension(*, _inline_js=True):
18 18
     """Enable ipywidgets, holoviews, and asyncio notebook integration."""
19 19
     if not in_ipynb():
20 20
         raise RuntimeError('"adaptive.notebook_extension()" may only be run '
... ...
@@ -27,7 +27,7 @@ def notebook_extension():
27 27
         _holoviews_enabled = False  # After closing a notebook the js is gone
28 28
         if not _holoviews_enabled:
29 29
             import holoviews
30
-            holoviews.notebook_extension('bokeh', logo=False)
30
+            holoviews.notebook_extension('bokeh', logo=False, inline=_inline_js)
31 31
             _holoviews_enabled = True
32 32
     except ModuleNotFoundError:
33 33
         warnings.warn("holoviews is not installed; plotting "
Browse code

fix live_plot

See https://github.com/pyviz/holoviews/issues/3564
and https://github.com/python-adaptive/adaptive/issues/166

Bas Nijholt authored on 19/03/2019 19:22:20
Showing 1 changed files
... ...
@@ -132,11 +132,13 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
132 132
     # off a thread (and learner is not threadsafe) or block the kernel.
133 133
 
134 134
     async def updater():
135
+        event = lambda: hv.streams.Stream.trigger(dm.streams) # XXX: used to be dm.event()
136
+        # see https://github.com/pyviz/holoviews/issues/3564
135 137
         try:
136 138
             while not runner.task.done():
137
-                dm.event()
139
+                event()
138 140
                 await asyncio.sleep(update_interval)
139
-            dm.event()  # fire off one last update before we die
141
+            event()  # fire off one last update before we die
140 142
         finally:
141 143
             if active_plotting_tasks[name] is asyncio.Task.current_task():
142 144
                 active_plotting_tasks.pop(name, None)
Browse code

fix whitespace issues

Joseph Weston authored on 20/12/2018 22:35:02
Showing 1 changed files
... ...
@@ -32,7 +32,7 @@ def notebook_extension():
32 32
     except ModuleNotFoundError:
33 33
         warnings.warn("holoviews is not installed; plotting "
34 34
                       "is disabled.", RuntimeWarning)
35
-    
35
+
36 36
     # Load ipywidgets
37 37
     try:
38 38
         if not _ipywidgets_enabled:
Browse code

adhere to PEP008 by using absolute imports

See https://www.python.org/dev/peps/pep-0008/#imports

Bas Nijholt authored on 26/11/2018 13:39:12
Showing 1 changed files
... ...
@@ -1,8 +1,9 @@
1 1
 # -*- coding: utf-8 -*-
2
-import importlib
2
+
3 3
 import asyncio
4 4
 from contextlib import suppress
5 5
 import datetime
6
+import importlib
6 7
 import random
7 8
 import warnings
8 9
 
Browse code

reload the holoviews javascript each time notebook_integration is called

Because after closing the notebook and then opening it, the javascript
is gone. Without this change, one could not load it again.

Bas Nijholt authored on 30/10/2018 13:34:34
Showing 1 changed files
... ...
@@ -23,6 +23,7 @@ def notebook_extension():
23 23
 
24 24
     # Load holoviews
25 25
     try:
26
+        _holoviews_enabled = False  # After closing a notebook the js is gone
26 27
         if not _holoviews_enabled:
27 28
             import holoviews
28 29
             holoviews.notebook_extension('bokeh', logo=False)
Browse code

exponentially decay message frequency in live_info

Jorn Hoofwijk authored on 20/09/2018 13:42:04 • Bas Nijholt committed on 22/10/2018 14:47:59
Showing 1 changed files
... ...
@@ -3,6 +3,7 @@ import importlib
3 3
 import asyncio
4 4
 from contextlib import suppress
5 5
 import datetime
6
+import random
6 7
 import warnings
7 8
 
8 9
 
... ...
@@ -150,6 +151,24 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
150 151
     return dm
151 152
 
152 153
 
154
+def should_update(status):
155
+    try:
156
+        # Get the length of the write buffer size
157
+        buffer_size = len(status.comm.kernel.iopub_thread._events)
158
+
159
+        # Make sure to only keep all the messages when the notebook
160
+        # is viewed, this means 'buffer_size == 1'. However, when not
161
+        # viewing the notebook the buffer fills up. When this happens
162
+        # we decide to only add messages to it when a certain probability.
163
+        # i.e. we're offline for 12h, with an update_interval of 0.5s,
164
+        # and without the reduced probability, we have buffer_size=86400.
165
+        # With the correction this is np.log(86400) / np.log(1.1) = 119.2
166
+        return 1.1**buffer_size * random.random() < 1
167
+    except Exception:
168
+        # We catch any Exception because we are using a private API.
169
+        return True
170
+
171
+
153 172
 def live_info(runner, *, update_interval=0.5):
154 173
     """Display live information about the runner.
155 174
 
... ...
@@ -172,7 +191,12 @@ def live_info(runner, *, update_interval=0.5):
172 191
     async def update():
173 192
         while not runner.task.done():
174 193
             await asyncio.sleep(update_interval)
175
-            status.value = _info_html(runner)
194
+
195
+            if should_update(status):
196
+                status.value = _info_html(runner)
197
+            else:
198
+                await asyncio.sleep(0.05)
199
+
176 200
         status.value = _info_html(runner)
177 201
         cancel.layout.display = 'none'
178 202
 
Browse code

improve 'notebook_extension' and add 'plotly' as a dependency

Bas Nijholt authored on 20/10/2018 13:04:45
Showing 1 changed files
... ...
@@ -7,28 +7,42 @@ import warnings
7 7
 
8 8
 
9 9
 _async_enabled = False
10
-_plotting_enabled = False
10
+_holoviews_enabled = False
11
+_ipywidgets_enabled = False
12
+_plotly_enabled = False
11 13
 
12 14
 
13 15
 def notebook_extension():
16
+    """Enable ipywidgets, holoviews, and asyncio notebook integration."""
14 17
     if not in_ipynb():
15 18
         raise RuntimeError('"adaptive.notebook_extension()" may only be run '
16 19
                            'from a Jupyter notebook.')
17 20
 
18
-    global _plotting_enabled
19
-    _plotting_enabled = False
21
+    global _async_enabled, _holoviews_enabled, _ipywidgets_enabled
22
+
23
+    # Load holoviews
24
+    try:
25
+        if not _holoviews_enabled:
26
+            import holoviews
27
+            holoviews.notebook_extension('bokeh', logo=False)
28
+            _holoviews_enabled = True
29
+    except ModuleNotFoundError:
30
+        warnings.warn("holoviews is not installed; plotting "
31
+                      "is disabled.", RuntimeWarning)
32
+    
33
+    # Load ipywidgets
20 34
     try:
21
-        import ipywidgets
22
-        import holoviews
23
-        holoviews.notebook_extension('bokeh', logo=False)
24
-        _plotting_enabled = True
35
+        if not _ipywidgets_enabled:
36
+            import ipywidgets
37
+            _ipywidgets_enabled = True
25 38
     except ModuleNotFoundError:
26
-        warnings.warn("holoviews and (or) ipywidgets are not installed; plotting "
39
+        warnings.warn("ipywidgets is not installed; live_info "
27 40
                       "is disabled.", RuntimeWarning)
28 41
 
29
-    global _async_enabled
30
-    get_ipython().magic('gui asyncio')
31
-    _async_enabled = True
42
+    # Enable asyncio integration
43
+    if not _async_enabled:
44
+        get_ipython().magic('gui asyncio')
45
+        _async_enabled = True
32 46
 
33 47
 
34 48
 def ensure_holoviews():
... ...
@@ -38,6 +52,22 @@ def ensure_holoviews():
38 52
         raise RuntimeError('holoviews is not installed; plotting is disabled.')
39 53
 
40 54
 
55
+def ensure_plotly():
56
+    global _plotly_enabled
57
+    try:
58
+        import plotly
59
+        if not _plotly_enabled:
60
+            import plotly.graph_objs
61
+            import plotly.figure_factory
62
+            import plotly.offline
63
+            # This injects javascript and should happen only once
64
+            plotly.offline.init_notebook_mode()
65
+            _plotly_enabled = True
66
+        return plotly
67
+    except ModuleNotFoundError:
68
+        raise RuntimeError('plotly is not installed; plotting is disabled.')
69
+
70
+
41 71
 def in_ipynb():
42 72
     try:
43 73
         # If we are running in IPython, then `get_ipython()` is always a global
... ...
@@ -72,7 +102,7 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
72 102
     dm : `holoviews.core.DynamicMap`
73 103
         The plot that automatically updates every `update_interval`.
74 104
     """
75
-    if not _plotting_enabled:
105
+    if not _holoviews_enabled:
76 106
         raise RuntimeError("Live plotting is not enabled; did you run "
77 107
                            "'adaptive.notebook_extension()'?")
78 108
 
... ...
@@ -126,7 +156,7 @@ def live_info(runner, *, update_interval=0.5):
126 156
     Returns an interactive ipywidget that can be
127 157
     visualized in a Jupyter notebook.
128 158
     """
129
-    if not _plotting_enabled:
159
+    if not _holoviews_enabled:
130 160
         raise RuntimeError("Live plotting is not enabled; did you run "
131 161
                            "'adaptive.notebook_extension()'?")
132 162
 
Browse code

fix live_info css

Bas Nijholt authored on 19/10/2018 13:24:42
Showing 1 changed files
... ...
@@ -176,7 +176,7 @@ def _info_html(runner):
176 176
     with suppress(Exception):
177 177
         info.append(('latest loss', f'{runner.learner._cache["loss"]:.3f}'))
178 178
 
179
-    template = '<dt>{}</dt><dd>{}</dd>'
179
+    template = '<dt class="ignore-css">{}</dt><dd>{}</dd>'
180 180
     table = '\n'.join(template.format(k, v) for k, v in info)
181 181
 
182 182
     return f'''
Browse code

add tutorials

Bas Nijholt authored on 17/10/2018 13:30:10
Showing 1 changed files
... ...
@@ -20,7 +20,7 @@ def notebook_extension():
20 20
     try:
21 21
         import ipywidgets
22 22
         import holoviews
23
-        holoviews.notebook_extension('bokeh')
23
+        holoviews.notebook_extension('bokeh', logo=False)
24 24
         _plotting_enabled = True
25 25
     except ModuleNotFoundError:
26 26
         warnings.warn("holoviews and (or) ipywidgets are not installed; plotting "
Browse code

add doc files

Bas Nijholt authored on 16/10/2018 18:10:12
Showing 1 changed files
... ...
@@ -56,21 +56,21 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
56 56
 
57 57
     Parameters
58 58
     ----------
59
-    runner : Runner
59
+    runner : `Runner`
60 60
     plotter : function
61 61
         A function that takes the learner as a argument and returns a
62
-        holoviews object. By default learner.plot() will be called.
62
+        holoviews object. By default ``learner.plot()`` will be called.
63 63
     update_interval : int
64 64
         Number of second between the updates of the plot.
65 65
     name : hasable
66 66
         Name for the `live_plot` task in `adaptive.active_plotting_tasks`.
67
-        By default the name is `None` and if another task with the same name
68
-        already exists that other live_plot is canceled.
67
+        By default the name is None and if another task with the same name
68
+        already exists that other `live_plot` is canceled.
69 69
 
70 70
     Returns
71 71
     -------
72
-    dm : holoviews.DynamicMap
73
-        The plot that automatically updates every update_interval.
72
+    dm : `holoviews.core.DynamicMap`
73
+        The plot that automatically updates every `update_interval`.
74 74
     """
75 75
     if not _plotting_enabled:
76 76
         raise RuntimeError("Live plotting is not enabled; did you run "
Browse code

fix bug 'ModuleNotFounderror' -> 'ModuleNotFoundError'

Bas Nijholt authored on 15/10/2018 16:32:49
Showing 1 changed files
... ...
@@ -34,7 +34,7 @@ def notebook_extension():
34 34
 def ensure_holoviews():
35 35
     try:
36 36
         return importlib.import_module('holoviews')
37
-    except ModuleNotFounderror:
37
+    except ModuleNotFoundError:
38 38
         raise RuntimeError('holoviews is not installed; plotting is disabled.')
39 39
 
40 40
 
Browse code

fix empty lines and remove unused import

Bas Nijholt authored on 15/10/2018 14:46:32
Showing 1 changed files
... ...
@@ -3,7 +3,6 @@ import importlib
3 3
 import asyncio
4 4
 from contextlib import suppress
5 5
 import datetime
6
-from pkg_resources import parse_version
7 6
 import warnings
8 7
 
9 8
 
Browse code

display the loss with 'live_info'

Bas Nijholt authored on 08/10/2018 13:16:54
Showing 1 changed files
... ...
@@ -174,6 +174,9 @@ def _info_html(runner):
174 174
     with suppress(Exception):
175 175
         info.append(('# of points', runner.learner.npoints))
176 176
 
177
+    with suppress(Exception):
178
+        info.append(('latest loss', f'{runner.learner._cache["loss"]:.3f}'))
179
+
177 180
     template = '<dt>{}</dt><dd>{}</dd>'
178 181
     table = '\n'.join(template.format(k, v) for k, v in info)
179 182
 
Browse code

use contextlib.suppress

Bas Nijholt authored on 10/07/2018 23:25:10
Showing 1 changed files
... ...
@@ -1,6 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import importlib
3 3
 import asyncio
4
+from contextlib import suppress
4 5
 import datetime
5 6
 from pkg_resources import parse_version
6 7
 import warnings
... ...
@@ -110,10 +111,8 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
110 111
             cancel_button.layout.display = 'none'  # remove cancel button
111 112
 
112 113
     def cancel(_):
113
-        try:
114
+        with suppress(KeyError):
114 115
             active_plotting_tasks[name].cancel()
115
-        except KeyError:
116
-            pass
117 116
 
118 117
     active_plotting_tasks[name] = runner.ioloop.create_task(updater())
119 118
     cancel_button.on_click(cancel)
... ...
@@ -172,10 +171,8 @@ def _info_html(runner):
172 171
         ('overhead', f'{runner.overhead():.2f}%'),
173 172
     ]
174 173
 
175
-    try:
174
+    with suppress(Exception):
176 175
         info.append(('# of points', runner.learner.npoints))
177
-    except Exception:
178
-        pass
179 176
 
180 177
     template = '<dt>{}</dt><dd>{}</dd>'
181 178
     table = '\n'.join(template.format(k, v) for k, v in info)
Browse code

remove 'performance' and define 'overhead' (1 - efficiecy)

Bas Nijholt authored on 16/06/2018 23:02:26
Showing 1 changed files
... ...
@@ -161,19 +161,15 @@ def live_info(runner, *, update_interval=0.5):
161 161
 def _info_html(runner):
162 162
     status = runner.status()
163 163
 
164
-    stat_color = {'cancelled': 'orange',
165
-                  'failed': 'red',
166
-                  'running': 'blue',
167
-                  'finished': 'green'}[status]
168
-
169
-    performance = runner.performance()
170
-    perf_color = 'green' if performance > 1 else 'red'
164
+    color = {'cancelled': 'orange',
165
+             'failed': 'red',
166
+             'running': 'blue',
167
+             'finished': 'green'}[status]
171 168
 
172 169
     info = [
173
-        ('status', f'<font color="{stat_color}">{status}</font>'),
170
+        ('status', f'<font color="{color}">{status}</font>'),
174 171
         ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
175
-        ('performance', f'<font color="{perf_color}">{performance:.1f}</font>'),
176
-        ('efficiency', f'{runner.efficiency():.2f}%'),
172
+        ('overhead', f'{runner.overhead():.2f}%'),
177 173
     ]
178 174
 
179 175
     try:
Browse code

calculate the actual efficiency of the resources

Bas Nijholt authored on 16/06/2018 22:32:07
Showing 1 changed files
... ...
@@ -173,6 +173,7 @@ def _info_html(runner):
173 173
         ('status', f'<font color="{stat_color}">{status}</font>'),
174 174
         ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
175 175
         ('performance', f'<font color="{perf_color}">{performance:.1f}</font>'),
176
+        ('efficiency', f'{runner.efficiency():.2f}%'),
176 177
     ]
177 178
 
178 179
     try:
Browse code

define a measure of 'performance'

Bas Nijholt authored on 16/06/2018 09:59:54
Showing 1 changed files
... ...
@@ -161,15 +161,18 @@ def live_info(runner, *, update_interval=0.5):
161 161
 def _info_html(runner):
162 162
     status = runner.status()
163 163
 
164
-    color = {'cancelled': 'orange',
165
-             'failed': 'red',
166
-             'running': 'blue',
167
-             'finished': 'green'}[status]
164
+    stat_color = {'cancelled': 'orange',
165
+                  'failed': 'red',
166
+                  'running': 'blue',
167
+                  'finished': 'green'}[status]
168
+
169
+    performance = runner.performance()
170
+    perf_color = 'green' if performance > 1 else 'red'
168 171
 
169 172
     info = [
170
-        ('status', f'<font color="{color}">{status}</font>'),
173
+        ('status', f'<font color="{stat_color}">{status}</font>'),
171 174
         ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
172
-        (f'efficiency', f'{runner.efficiency():.1f}%'),
175
+        ('performance', f'<font color="{perf_color}">{performance:.1f}</font>'),
173 176
     ]
174 177
 
175 178
     try:
Browse code

correctly keep track of the average time

Bas Nijholt authored on 16/06/2018 09:07:44
Showing 1 changed files
... ...
@@ -166,13 +166,10 @@ def _info_html(runner):
166 166
              'running': 'blue',
167 167
              'finished': 'green'}[status]
168 168
 
169
-    t_total = runner.elapsed_time()
170
-    efficiency = (t_total - runner.time_ask_tell) / t_total * 100
171
-
172 169
     info = [
173 170
         ('status', f'<font color="{color}">{status}</font>'),
174
-        ('elapsed time', datetime.timedelta(seconds=t_total)),
175
-        (f'efficiency', f'{efficiency:.1f}%'),
171
+        ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
172
+        (f'efficiency', f'{runner.efficiency():.1f}%'),
176 173
     ]
177 174
 
178 175
     try:
Browse code

measure the efficiency of the runner

Bas Nijholt authored on 15/06/2018 05:58:51
Showing 1 changed files
... ...
@@ -166,9 +166,13 @@ def _info_html(runner):
166 166
              'running': 'blue',
167 167
              'finished': 'green'}[status]
168 168
 
169
+    t_total = runner.elapsed_time()
170
+    efficiency = (t_total - runner.time_ask_tell) / t_total * 100
171
+
169 172
     info = [
170 173
         ('status', f'<font color="{color}">{status}</font>'),
171
-        ('elapsed time', datetime.timedelta(seconds=runner.elapsed_time())),
174
+        ('elapsed time', datetime.timedelta(seconds=t_total)),
175
+        (f'efficiency', f'{efficiency:.1f}%'),
172 176
     ]
173 177
 
174 178
     try:
Browse code

remove 'description' argument in ipywidgets.HBox because it's deprecated

> This is deprecated in traitlets 4.2. This error will be raised in a future release of traitlets.

Bas Nijholt authored on 24/05/2018 07:47:31
Showing 1 changed files
... ...
@@ -152,7 +152,6 @@ def live_info(runner, *, update_interval=0.5):
152 152
 
153 153
     display(ipywidgets.HBox(
154 154
         (status, cancel),
155
-        description='Runner stats',
156 155
         layout=ipywidgets.Layout(border='solid 1px',
157 156
                                  width='200px',
158 157
                                  align_items='center'),
Browse code

fix the warning message when holoviews and (or) ipywidgets are not installed

Bas Nijholt authored on 03/03/2018 20:00:31
Showing 1 changed files
... ...
@@ -23,7 +23,7 @@ def notebook_extension():
23 23
         holoviews.notebook_extension('bokeh')
24 24
         _plotting_enabled = True
25 25
     except ModuleNotFoundError:
26
-        warnings.warn("holoviews and ipywidgets are not installed; plotting "
26
+        warnings.warn("holoviews and (or) ipywidgets are not installed; plotting "
27 27
                       "is disabled.", RuntimeWarning)
28 28
 
29 29
     global _async_enabled
Browse code

remove cancel button when runner or live plot stops

This provides a better UX than leaving a useless button dangling.

Joseph Weston authored on 19/02/2018 14:45:12
Showing 1 changed files
... ...
@@ -80,6 +80,9 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
80 80
     import ipywidgets
81 81
     from IPython.display import display
82 82
 
83
+    if name in active_plotting_tasks:
84
+        active_plotting_tasks[name].cancel()
85
+
83 86
     def plot_generator():
84 87
         while True:
85 88
             if not plotter:
... ...
@@ -89,7 +92,8 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
89 92
 
90 93
     dm = hv.DynamicMap(plot_generator(),
91 94
                        streams=[hv.streams.Stream.define('Next')()])
92
-
95
+    cancel_button = ipywidgets.Button(description='cancel live-plot',
96
+                                      layout=ipywidgets.Layout(width='150px'))
93 97
 
94 98
     # Could have used dm.periodic in the following, but this would either spin
95 99
     # off a thread (and learner is not threadsafe) or block the kernel.
... ...
@@ -103,12 +107,7 @@ def live_plot(runner, *, plotter=None, update_interval=2, name=None):
103 107
         finally:
104 108
             if active_plotting_tasks[name] is asyncio.Task.current_task():
105 109
                 active_plotting_tasks.pop(name, None)
106
-
107
-    global active_plotting_tasks
108
-    if name in active_plotting_tasks:
109
-        active_plotting_tasks[name].cancel()
110
-
111
-    active_plotting_tasks[name] = asyncio.get_event_loop().create_task(updater())
110
+            cancel_button.layout.display = 'none'  # remove cancel button
112 111