Exemple #1
0
 def __init__(self, net, width="95%", height="550px", play_rate=0.5):
     self._ignore_layer_updates = False
     self.player = _Player(self, play_rate)
     self.player.start()
     self.net = net
     self.dataset = net.dataset
     self._width = width
     self._height = height
     ## Global widgets:
     style = {"description_width": "initial"}
     self.feature_columns = IntText(description="Feature columns:",
                                    value=3,
                                    style=style)
     self.feature_scale = FloatText(description="Feature scale:",
                                    value=2.0,
                                    style=style)
     self.feature_columns.observe(self.regenerate, names='value')
     self.feature_scale.observe(self.regenerate, names='value')
     ## Hack to center SVG as justify-content is broken:
     self.net_svg = HTML(value="""<p style="text-align:center">%s</p>""" %
                         ("", ),
                         layout=Layout(width=self._width,
                                       overflow_x='auto',
                                       overflow_y="auto",
                                       justify_content="center"))
     # Make controls first:
     self.output = Output()
     controls = self.make_controls()
     config = self.make_config()
     super().__init__([config, controls, self.net_svg, self.output])
Exemple #2
0
class SearchWidget:

    def __init__(self):
        self.search = Text(placeholder='Name')
        self.go_btn = Button(description='Search')
        self.clear_btn = Button(description='Clear')
        self.out = Output()

        self.search.continuous_update = False
        self.search.observe(self.do_search, 'value')
        self.go_btn.on_click(self.do_search)
        self.clear_btn.on_click(self.do_clear)

    def do_clear(self, cb):
        self.out.clear_output()

    def do_search(self, cb):
        name = self.search.value

        self.out.clear_output()

        with self.out:
            obj = env.project[name]
            if obj.exists():
                display(obj.gui.header())
            else:
                print(f"{obj.name} valid, but doesn't exist")

    def as_widget(self):
        return VBox([HBox([self.search, self.go_btn, self.clear_btn]), self.out])
Exemple #3
0
 def create_interactive_widgets(self, start_handler, stop_handler):
     """
     This method will create the necessary ipywidget objects and return the final Box to display.
     :return:
     """
     self.start_streaming_button = ToggleButton(
         description='Start Streaming',
         value=False,
         disabled=False,
         button_style='',
         tooltip='Start Streaming',
         icon='play'  # (FontAwesome names without the `fa-` prefix)
     )
     self.stop_streaming_button = ToggleButton(
         description='Stop Streaming',
         value=True,
         disabled=False,
         button_style='',
         tooltip='Stop Streaming',
         icon='stop'  # (FontAwesome names without the `fa-` prefix)
     )
     self.output_area = Output()
     self.start_handler = start_handler
     self.stop_handler = stop_handler
     self.start_streaming_button.observe(
         self.start_streaming_button_handler)
     self.stop_streaming_button.observe(self.stop_streaming_button_handler)
     self.display_holder = VBox([
         HBox([self.start_streaming_button, self.stop_streaming_button]),
         self.output_area
     ])
     return self.display_holder
    def refresh(self) -> None:
        """Refresh (render) the progress information."""
        if self.console.is_jupyter:  # pragma: no cover
            try:
                from ipywidgets import Output
                from IPython.display import display
            except ImportError:
                import warnings

                warnings.warn('install "ipywidgets" for Jupyter support')
            else:
                with self._lock:
                    if self.ipy_widget is None:
                        self.ipy_widget = Output()
                        display(self.ipy_widget)

                    with self.ipy_widget:
                        self.ipy_widget.clear_output(wait=True)
                        self.console.print(self.get_renderable())

        elif self.console.is_terminal and not self.console.is_dumb_terminal:
            with self._lock:
                self._live_render.set_renderable(self.get_renderable())
                with self.console:
                    self.console.print(Control(""))
Exemple #5
0
 def __init__(self, base=None, filetype='*.msh5', N=None):
     if N is None:
         N = int(input('how many spectra do you want to compare:  '))
     self.Chooser = FileChooser(base=base,
                                filetype=filetype,
                                mode='r',
                                show=False)
     self.bsel = widgets.Button(
         description='Copy',
         layout=Layout(width='10%'),
         button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
         tooltip='copy selected data-set to entry below')
     self.to = widgets.IntText(value=1,
                               min=1,
                               max=N,
                               layout=Layout(width='10%'))
     self.bsel.on_click(self.copy)
     self.bdisplay = widgets.Button(
         description='Display',
         layout=Layout(width='10%'),
         button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
         tooltip='display superimposition')
     self.bdisplay.on_click(self.display)
     self.spec = Output(layout={'border': '1px solid black'})
     self.DataList = [SpforSuper(i + 1, 'None') for i in range(N)]
     self.DataList[0].color.value = 'black'
     self.DataList[0].fig = True  # switches on the very first one
Exemple #6
0
 def _cb(pts):
     if pts_callback:
         pts_callback(pts, rej, box)
     else:
         out = Output()
         box.children = tuple(list(box.children) + [out])
         out.append_stdout(pts)
Exemple #7
0
class TerminalTab(object):
    def __init__(self):
        # self.tab = Output(layout={'height': '600px'})
        self.tab = Output(layout={'height': 'auto'})
        self.tab.append_display_data(HTML(filename='doc/about.html'))

        from ipywidgets import HTML, Tab, Layout
 def __init__(
     self,
     deviation,
     angular_tolerance,
     edge_accuracy,
     debug,
     cad_width,
     height,
     sidecar=None,
     show_result=True,
 ):
     self.debug_output = Output()
     self.deviation = deviation
     self.angular_tolerance = angular_tolerance
     self.edge_accuracy = edge_accuracy
     self.debug = debug
     self.cad_width = cad_width
     self.height = height
     self.sidecar = sidecar
     self.show_result = show_result
     self.reset_camera = True
     self.indexes = []
     self.stack = None
     self.result = None
     self.bbox = None
     self.select_box = None
Exemple #9
0
    def create(self, rows=30, path="/", height="400px"):
        if self.running:
            print("dbfs browser already running. Use close() first")
            return
        self.path = path
        self.flist = Select(options=[],
                            disabled=False,
                            layout={"height": height})
        self.flist.observe(self.on_click, names="value")

        self.refresh = Button(icon="refresh", layout={"width": "40px"})
        self.refresh.on_click(self.on_refresh)
        self.path_view = Output()
        self.preview = Output(
            layout={
                "width": "800px",
                "height": height,
                "overflow": "scroll",
                "border": "1px solid gray",
            })

        self.up = Button(icon="arrow-up", layout={"width": "40px"})
        self.up.on_click(self.on_up)

        display(
            VBox([
                HBox([self.refresh, self.up, self.path_view]),
                HBox([self.flist, self.preview]),
            ]))

        self.update()
        self.running = True
Exemple #10
0
 def __init__(self, querier, worklist, force=False, debug=False, index=0):
     reload()
     self.worklist = worklist
     self.force = force
     self.querier = querier
     self.next_page_widget = Button(description='Next Work', icon='fa-arrow-right')
     self.reload_widget = Button(description='Reload', icon='fa-refresh')
     self.previous_page_widget = Button(description='Previous Work', icon='fa-arrow-left')
     self.debug_widget = ToggleButton(value=debug, description="Debug")
     self.textarea_widget = ToggleButton(value=False, description="TextArea")
     self.page_number_widget = Label(value="")
     self.output_widget = Output()
     self.next_page_widget.on_click(self.next_page)
     self.reload_widget.on_click(self.reload)
     self.previous_page_widget.on_click(self.previous_page)
     self.textarea_widget.observe(self.show)
     self.view = VBox([
         HBox([
             self.previous_page_widget,
             self.reload_widget,
             self.next_page_widget,
             self.debug_widget,
             self.textarea_widget,
             self.page_number_widget
         ]),
         self.output_widget
     ])
     self.index = index
     self.varname = ""
     self.work = None
     self.articles = []
     self.reload(show=False)
    def create(self, height=300, db_width=150, tbl_width=200, schema_width=700):
        console = Output(layout={"height": "28px"})
        schema = Output(
            layout={
                "height": _px(height),
                "width": _px(schema_width),
                "border": "1px solid grey",
                "overflow": "scroll",
            }
        )
        data = Output()

        tbl = TableList(self.spark, console, schema, data)
        tbl.create(width=tbl_width, height=height)

        db = DatabaseList(self.spark, console, tbl)
        db.create(width=db_width, height=height)

        display(
            VBox(
                [
                    HBox(
                        [
                            VBox([db.refresh, db.list]),
                            VBox([tbl.refresh, tbl.list]),
                            VBox([console, schema]),
                        ]
                    ),
                    data,
                ]
            )
        )
    def expanded_c():
        # here we expand vertically and use the full remaining width
        width_str = "{}".format(remaining_width)
        srm = record._get_single_value(SmoothReservoirModel)
        with plt.ioff():
            fig = plt.figure()
            rect = 0, 0, 0.8, 1.2  # l, b, w, h
            ax = fig.add_axes(rect)

        graph_out = Output(layout=Layout(
            height='auto',
            width=width_str,
            description="Compartmental Graph",
        ))
        with graph_out:
            ax.clear()
            srm.plot_pools_and_fluxes(ax)
            display(ax.figure)
            plt.close(fig)

        outs = [
            Output(layout=Layout(width=width_str))
            for i, t in enumerate(types_expanded)
        ]
        for i, t in enumerate(types_expanded):
            with outs[i]:
                display(record._get_single_value(t))

        return [VBox([graph_out] + outs)]
Exemple #13
0
class MpltFigureViewerWidget(HBox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._current_cell = None

        self.layout = Layout(
            display="none",
            flex_direction="row",
            border="solid 1px gray",
            width="100%",
            height="auto",
            overflow="auto",
        )
        self._output = Output()
        self.children = [self._output]

    def reset(self):
        self._output.clear_output()
        self.layout.display = "none"
        self._current_cell = None

    def show_figure(self, figure, cell):
        if self.layout.display != "flex":
            self.layout.display = "flex"
        if self._current_cell is not None:
            self._current_cell.unselect_figure()
        self._current_cell = cell
        self._output.clear_output()
        with self._output:
            if hasattr(figure, "canvas"):
                display(figure.canvas)
            else:
                display(figure)
Exemple #14
0
    def __init__(self, es: ExplorerThresholds, parent_widget=None):
        super().__init__(parent_widget=parent_widget)
        self.selector = es
        self.report_picker = Dropdown(
            options=[
                ' ', _report_picker_current_selection,
                _report_picker_build_nobuild, 'Other Report'
            ],
            value=' ',
            description='Choose:',
            disabled=False,
        )
        self.report_picker.observe(self.report_picker_action)

        self.second_picker = Dropdown(
            options=(" ", ),
            value=' ',
            description=" ",
            disabled=False,
        )
        self.second_picker.layout.visibility = 'hidden'

        self.report_pane = Output(layout=Layout(width='7.5in', ), )
        self.make_stack(
            self.report_picker,
            self.second_picker,
            self.report_pane,
        )

        self.next_button.disabled = True
Exemple #15
0
    def refresh(self) -> None:
        """Update the display of the Live Render."""
        if self.console.is_jupyter:  # pragma: no cover
            try:
                from IPython.display import display
                from ipywidgets import Output
            except ImportError:
                import warnings

                warnings.warn('install "ipywidgets" for Jupyter support')
            else:
                with self._lock:
                    if self.ipy_widget is None:
                        self.ipy_widget = Output()
                        display(self.ipy_widget)

                    with self.ipy_widget:
                        self.ipy_widget.clear_output(wait=True)
                        self.console.print(self._live_render.renderable)
        elif self.console.is_terminal and not self.console.is_dumb_terminal:
            with self._lock, self.console:
                self.console.print(Control(""))
        elif (
            not self._started and not self.transient
        ):  # if it is finished allow files or dumb-terminals to see final result
            with self.console:
                self.console.print(Control(""))
Exemple #16
0
    def __init__(self,
                 df: pd.DataFrame,
                 options_col: str,
                 result_col: str = "label",
                 show_callback: Callable = None,
                 auto_fill_in: bool = True):
        """
        - df: pd.DataFrame, a dataframe prepared
        - options_col: str, column name assigned with options
        - result_col: str, default 'label',
            column name we'll assign the labels
        - auto_fill_in: bool, defult True, do we fill in the label
            automatically if there is only one option
        """
        self.df = df
        self.result_col = result_col
        self.options_col = options_col

        if auto_fill_in:
            self.df.loc[:,self.result_col] = self.df[self.options_col]\
                .apply(lambda x:x[0] if len(x)==1 else None)
        else:
            self.df.loc[:, self.result_col] = [
                None,
            ] * len(self.df)

        self.out = Output()
        show_dict = lambda idx, row: str(dict(row))
        self.show_callback = show_dict if show_callback is None else show_callback
Exemple #17
0
    def __init__(self):
        # self.tab = Output(layout={'height': '900px'})
        # self.tab = Output(layout={height=’85%’,min_height=’350px’})
        self.tab = Output(layout={'height': 'auto'})

        # WHY? -good works; -bad, doesn't
        # self.tab.append_display_data(HTML(filename='doc/about-good.html'))
        self.tab.append_display_data(HTML(filename='doc/about-bad.html'))
Exemple #18
0
    def setup(self, *_, **__) -> "TopTokensDisplayer":

        self._table = gu.DataGridOutput() if not self.simple_display else None
        self._output = Output() if self.simple_display else None

        self.start_observe()

        return self
 def __init__(self, id_string='', width=12, height=2.5, show_plot=True):
     """A dynamic plotting widget for tracking training progress in notebooks."""
     self.id_string = id_string
     self.width = width
     self.height = height
     self.output = Output()
     self.metrics = defaultdict(list)
     self.show_plot = show_plot
Exemple #20
0
 def __init__(self, debug, cad_width, height):
     self.debug_output = Output()
     self.debug = debug
     self.cad_width = cad_width
     self.height = height
     self.display = CadqueryDisplay()
     widget = self.display.create(height=height, cad_width=cad_width)
     self.display.display(widget)
Exemple #21
0
def load_audio_frame(filename, frame, context=1):
    output = Output(layout={
        'width': '100%',
        'align-items': 'center',
        'display': 'flex'
    })
    output.append_display_data(load_audio_frame_raw(filename, frame, context))
    return output
class Plotter(object):
    def __init__(self, id_string='', width=12, height=2.5, show_plot=True):
        """A dynamic plotting widget for tracking training progress in notebooks."""
        self.id_string = id_string
        self.width = width
        self.height = height
        self.output = Output()
        self.metrics = defaultdict(list)
        self.show_plot = show_plot

    def update(self, **metrics):
        for k, v in metrics.items():
            if type(v) is list:
                self.metrics[k] += v
            else:
                self.metrics[k].append(v)

        self.output.clear_output(wait=True)
        with self.output:
            if self.show_plot:
                self.plot()
                plt.show()
            maxlen = max(map(len, self.metrics.keys()))
            print(self.id_string)
            for k, v in self.metrics.items():
                print(('%' + str(maxlen) + 's') % k,
                      '| current = %.2e' % v[-1],
                      '| max = %.2e (iter %4d)' % (np.max(v), np.argmax(v)),
                      '| min = %.2e (iter %4d)' % (np.min(v), np.argmin(v)))

    def show(self):
        display(self.output)

    def progress_string(self):
        s = self.id_string + '\n'
        maxlen = max(map(len, self.metrics.keys()))
        for k, v in self.metrics.items():
            s += ''.join([
                ('%' + str(maxlen) + 's') % k,
                '| current = %.2e' % v[-1],
                '| max = %.2e (iter %4d)' % (np.max(v), np.argmax(v)),
                '| min = %.2e (iter %4d)' % (np.min(v), np.argmin(v))
            ])
            s += '\n'
        return s

    def plot(self):
        fig = plt.figure(figsize=(self.width, self.height * len(self.metrics)))
        axs = fig.subplots(len(self.metrics))
        fig.suptitle(self.id_string)
        if len(self.metrics) == 1:
            axs = [axs]
        for ax, (k, v) in zip(axs, self.metrics.items()):
            ax.plot(v)
            ax.grid()
            ax.set_title(k)
        plt.tight_layout(rect=[0, 0.03, 1, 0.95])
        return fig
    def __init__(self, debug=False, cad_width=600, height=600):
        self._debug = debug

        self.debug_output = Output()
        self.cad_width = cad_width
        self.height = height
        self.indexes = [0]
        self.view = None
        self.state = None
Exemple #24
0
    def __init__(self):
        self.search = Text(placeholder='Name')
        self.go_btn = Button(description='Search')
        self.clear_btn = Button(description='Clear')
        self.out = Output()

        self.search.continuous_update = False
        self.search.observe(self.do_search, 'value')
        self.go_btn.on_click(self.do_search)
        self.clear_btn.on_click(self.do_clear)
Exemple #25
0
 def __init__(self):
     # self.tab = Output(layout={'height': '600px'})
     self.tab = Output(layout={'height': 'auto'})
     # self.tab.append_display_data(HTML(filename='doc/code.html'))
     custom_code_file = open("src/custom_modules/custom.cpp", "r")
     code_str = custom_code_file.read()
     # print(code_str)
     self.tab.append_display_data(
         HTML('<textarea readonly rows="20" cols="110">' + code_str +
              '</textarea>'))
Exemple #26
0
 def __init__(self, directory, output_directory=None):
     self.input_directory = directory
     self.output_dir = self.set_output_dir(output_directory)
     self.examples = self.list_examples_to_annotate()
     self.cursor = 0
     self.annotations = []
     self.progress_message = HTML()
     self.output_message = Output()
     self.output_image = Output()
     self.label_buttons, self.submit_button = self.make_all_buttons()
Exemple #27
0
class SuperImpose(object):
    "a tool to superimpose spectra"

    def __init__(self, base=None, filetype='*.msh5', N=None):
        if N is None:
            N = int(input('how many spectra do you want to compare:  '))
        self.Chooser = FileChooser(base=base,
                                   filetype=filetype,
                                   mode='r',
                                   show=False)
        self.bsel = widgets.Button(
            description='Copy',
            layout=Layout(width='10%'),
            button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
            tooltip='copy selected data-set to entry below')
        self.to = widgets.IntText(value=1,
                                  min=1,
                                  max=N,
                                  layout=Layout(width='10%'))
        self.bsel.on_click(self.copy)
        self.bdisplay = widgets.Button(
            description='Display',
            layout=Layout(width='10%'),
            button_style='info',  # 'success', 'info', 'warning', 'danger' or ''
            tooltip='display superimposition')
        self.bdisplay.on_click(self.display)
        self.spec = Output(layout={'border': '1px solid black'})
        self.DataList = [SpforSuper(i + 1, 'None') for i in range(N)]
        self.DataList[0].color.value = 'black'
        self.DataList[0].fig = True  # switches on the very first one

    def Show(self):
        display(
            widgets.Label(
                'Select a file, and click on the Copy button to copy it to the chosen slot'
            ))
        self.Chooser.show()
        display(HBox([self.bsel, widgets.Label('to'), self.to]))
        display(VBox([sp.me for sp in self.DataList]))
        display(self.bdisplay)
        display(self.spec)

    def copy(self, event):
        if self.to.value < 1 or self.to.value > len(self.DataList):
            print('Destination is out of range !')
        else:
            self.DataList[self.to.value - 1].name.value = self.Chooser.file
            self.DataList[self.to.value - 1].direct.value = 'up'
        self.to.value = min(self.to.value, len(self.DataList)) + 1

    def display(self, event):
        self.spec.clear_output(wait=True)
        for i, s in enumerate(self.DataList):
            with self.spec:
                s.display()
Exemple #28
0
 def __init__(self, title, function, length, play_rate=0.5):
     self.player = _Player(self, play_rate)
     self.player.start()
     self.title = title
     self.function = function
     self.length = length
     self.output = Output()
     self.position_text = IntText(value=0, layout=Layout(width="100%"))
     self.total_text = Label(value="of %s" % self.length, layout=Layout(width="100px"))
     controls = self.make_controls()
     super().__init__([controls, self.output])
Exemple #29
0
 def toggle_lineout(self, change):
     if change['new']:
         # start a new thread so the interaction with original figure won't be blocked
         self.observer_thrd = threading.Thread(
             target=self.__new_lineout_plot)
         self.observer_thrd.daemon = True
         self.observer_thrd.start()
         # display(self.out)
     else:
         self.observer_thrd.join()  # kill the thread
         Output.clear_output(self.out)
Exemple #30
0
    def __init__(self, settings):

        self.settings = settings

        # the 'out' construction is to refresh the text output at each update
        # to stop text building up in the widget display
        self.out = Output()

        words = ['Measure', 'Delete Last Measurement', 'Save Data', 'Save Fig']
        self.buttons = [
            widgets.Button(description=w, layout=Layout(width='25%'))
            for w in words
        ]
        self.buttons[0].button_style = 'success'
        self.buttons[0].style.font_weight = 'bold'
        self.buttons[1].button_style = 'warning'
        self.buttons[1].style.font_weight = 'bold'
        self.buttons[2].button_style = 'primary'
        self.buttons[2].style.font_weight = 'bold'
        self.buttons[3].button_style = 'primary'
        self.buttons[3].style.font_weight = 'bold'
        display(widgets.HBox(self.buttons))

        try:
            dvma.start_stream(settings)
            self.rec = dvma.streams.REC
        except:
            print('Data stream not initialised.')
            print(
                'Possible reasons: pyaudio or PyDAQmx not installed, or acquisition hardware not connected.'
            )
            print('Please note that it won' 't be possible to log data.')

        self.f = np.array([])
        self.G = np.array([])
        self.fig, self.ax = plt.subplots(1, 1, figsize=(9, 5), dpi=100)
        self.ax.set_xlabel('Frequency (Hz)')
        self.ax.set_ylabel('Amplitude (dB)')
        self.ax.grid()
        self.ax.set_xlim([0, 500])
        self.ax.set_ylim([-50, 50])
        self.line, = self.ax.plot([], [],
                                  'x',
                                  markeredgewidth=2,
                                  label='stepped sine')
        self.line.axes.set_autoscaley_on(True)

        self.buttons[0].on_click(self.measure)
        self.buttons[1].on_click(self.undo)
        self.buttons[2].on_click(self.save)
        self.buttons[3].on_click(self.savefig)

        display(self.out)
def test_append_stderr():
    output = Output()

    # Try appending a message to stderr.
    output.append_stderr("snakes!")
    expected = (_make_stream_output("snakes!", "stderr"),)
    assert output.outputs == expected, repr(output.outputs)

    # Try appending a second message.
    output.append_stderr("more snakes!")
    expected += (_make_stream_output("more snakes!", "stderr"),)
    assert output.outputs == expected, repr(output.outputs)
Exemple #32
0
 def __init__(self, net, width="95%", height="550px", play_rate=0.5):
     self._ignore_layer_updates = False
     self.player = _Player(self, play_rate)
     self.player.start()
     self.net = net
     r = random.randint(1, 1000000)
     self.class_id = "picture-dashboard-%s-%s" % (self.net.name, r)
     self._width = width
     self._height = height
     ## Global widgets:
     style = {"description_width": "initial"}
     self.feature_columns = IntText(description="Detail columns:",
                                    value=self.net.config["dashboard.features.columns"],
                                    min=0,
                                    max=1024,
                                    style=style)
     self.feature_scale = FloatText(description="Detail scale:",
                                    value=self.net.config["dashboard.features.scale"],
                                    min=0.1,
                                    max=10,
                                    style=style)
     self.feature_columns.observe(self.regenerate, names='value')
     self.feature_scale.observe(self.regenerate, names='value')
     ## Hack to center SVG as justify-content is broken:
     self.net_svg = HTML(value="""<p style="text-align:center">%s</p>""" % ("",), layout=Layout(
         width=self._width, overflow_x='auto', overflow_y="auto",
         justify_content="center"))
     # Make controls first:
     self.output = Output()
     controls = self.make_controls()
     config = self.make_config()
     super().__init__([config, controls, self.net_svg, self.output])
Exemple #33
0
 def __init__(self, title, function, length, play_rate=0.5):
     self.player = _Player(self, play_rate)
     self.player.start()
     self.title = title
     self.function = function
     self.length = length
     self.output = Output()
     self.position_text = IntText(value=0, layout=Layout(width="100%"))
     self.total_text = Label(value="of %s" % self.length, layout=Layout(width="100px"))
     controls = self.make_controls()
     super().__init__([controls, self.output])
def test_append_display_data():
    output = Output()

    # Try appending a Markdown object.
    output.append_display_data(Markdown("# snakes!"))
    expected = (
        {
            'output_type': 'display_data',
            'data': {
                'text/plain': '<IPython.core.display.Markdown object>',
                'text/markdown': '# snakes!'
            },
            'metadata': {}
        },
    )
    assert output.outputs == expected, repr(output.outputs)

    # Now try appending an Image.
    image_data = b"foobar"
    image_data_b64 = image_data if sys.version_info[0] < 3 else 'Zm9vYmFy\n'

    output.append_display_data(Image(image_data, width=123, height=456))
    expected += (
        {
            'output_type': 'display_data',
            'data': {
                'image/png': image_data_b64,
                'text/plain': '<IPython.core.display.Image object>'
            },
            'metadata': {
                'image/png': {
                    'width': 123,
                    'height': 456
                }
            }
        },
    )
    assert output.outputs == expected, repr(output.outputs)
Exemple #35
0
class Dashboard(VBox):
    """
    Build the dashboard for Jupyter widgets. Requires running
    in a notebook/jupyterlab.
    """
    def __init__(self, net, width="95%", height="550px", play_rate=0.5):
        self._ignore_layer_updates = False
        self.player = _Player(self, play_rate)
        self.player.start()
        self.net = net
        r = random.randint(1, 1000000)
        self.class_id = "picture-dashboard-%s-%s" % (self.net.name, r)
        self._width = width
        self._height = height
        ## Global widgets:
        style = {"description_width": "initial"}
        self.feature_columns = IntText(description="Detail columns:",
                                       value=self.net.config["dashboard.features.columns"],
                                       min=0,
                                       max=1024,
                                       style=style)
        self.feature_scale = FloatText(description="Detail scale:",
                                       value=self.net.config["dashboard.features.scale"],
                                       min=0.1,
                                       max=10,
                                       style=style)
        self.feature_columns.observe(self.regenerate, names='value')
        self.feature_scale.observe(self.regenerate, names='value')
        ## Hack to center SVG as justify-content is broken:
        self.net_svg = HTML(value="""<p style="text-align:center">%s</p>""" % ("",), layout=Layout(
            width=self._width, overflow_x='auto', overflow_y="auto",
            justify_content="center"))
        # Make controls first:
        self.output = Output()
        controls = self.make_controls()
        config = self.make_config()
        super().__init__([config, controls, self.net_svg, self.output])

    def propagate(self, inputs):
        """
        Propagate inputs through the dashboard view of the network.
        """
        if dynamic_pictures_check():
            return self.net.propagate(inputs, class_id=self.class_id, update_pictures=True)
        else:
            self.regenerate(inputs=input)

    def goto(self, position):
        if len(self.net.dataset.inputs) == 0 or len(self.net.dataset.targets) == 0:
            return
        if self.control_select.value == "Train":
            length = len(self.net.dataset.train_inputs)
        elif self.control_select.value == "Test":
            length = len(self.net.dataset.test_inputs)
        #### Position it:
        if position == "begin":
            self.control_slider.value = 0
        elif position == "end":
            self.control_slider.value = length - 1
        elif position == "prev":
            if self.control_slider.value - 1 < 0:
                self.control_slider.value = length - 1 # wrap around
            else:
                self.control_slider.value = max(self.control_slider.value - 1, 0)
        elif position == "next":
            if self.control_slider.value + 1 > length - 1:
                self.control_slider.value = 0 # wrap around
            else:
                self.control_slider.value = min(self.control_slider.value + 1, length - 1)
        self.position_text.value = self.control_slider.value


    def change_select(self, change=None):
        """
        """
        self.update_control_slider(change)
        self.regenerate()

    def update_control_slider(self, change=None):
        self.net.config["dashboard.dataset"] = self.control_select.value
        if len(self.net.dataset.inputs) == 0 or len(self.net.dataset.targets) == 0:
            self.total_text.value = "of 0"
            self.control_slider.value = 0
            self.position_text.value = 0
            self.control_slider.disabled = True
            self.position_text.disabled = True
            for child in self.control_buttons.children:
                if not hasattr(child, "icon") or child.icon != "refresh":
                    child.disabled = True
            return
        if self.control_select.value == "Test":
            self.total_text.value = "of %s" % len(self.net.dataset.test_inputs)
            minmax = (0, max(len(self.net.dataset.test_inputs) - 1, 0))
            if minmax[0] <= self.control_slider.value <= minmax[1]:
                pass # ok
            else:
                self.control_slider.value = 0
            self.control_slider.min = minmax[0]
            self.control_slider.max = minmax[1]
            if len(self.net.dataset.test_inputs) == 0:
                disabled = True
            else:
                disabled = False
        elif self.control_select.value == "Train":
            self.total_text.value = "of %s" % len(self.net.dataset.train_inputs)
            minmax = (0, max(len(self.net.dataset.train_inputs) - 1, 0))
            if minmax[0] <= self.control_slider.value <= minmax[1]:
                pass # ok
            else:
                self.control_slider.value = 0
            self.control_slider.min = minmax[0]
            self.control_slider.max = minmax[1]
            if len(self.net.dataset.train_inputs) == 0:
                disabled = True
            else:
                disabled = False
        self.control_slider.disabled = disabled
        self.position_text.disbaled = disabled
        self.position_text.value = self.control_slider.value
        for child in self.control_buttons.children:
            if not hasattr(child, "icon") or child.icon != "refresh":
                child.disabled = disabled

    def update_zoom_slider(self, change):
        if change["name"] == "value":
            self.net.config["svg_scale"] = self.zoom_slider.value
            self.regenerate()

    def update_position_text(self, change):
        # {'name': 'value', 'old': 2, 'new': 3, 'owner': IntText(value=3, layout=Layout(width='100%')), 'type': 'change'}
        self.control_slider.value = change["new"]

    def get_current_input(self):
        if self.control_select.value == "Train" and len(self.net.dataset.train_targets) > 0:
            return self.net.dataset.train_inputs[self.control_slider.value]
        elif self.control_select.value == "Test" and len(self.net.dataset.test_targets) > 0:
            return self.net.dataset.test_inputs[self.control_slider.value]

    def get_current_targets(self):
        if self.control_select.value == "Train" and len(self.net.dataset.train_targets) > 0:
            return self.net.dataset.train_targets[self.control_slider.value]
        elif self.control_select.value == "Test" and len(self.net.dataset.test_targets) > 0:
            return self.net.dataset.test_targets[self.control_slider.value]

    def update_slider_control(self, change):
        if len(self.net.dataset.inputs) == 0 or len(self.net.dataset.targets) == 0:
            self.total_text.value = "of 0"
            return
        if change["name"] == "value":
            self.position_text.value = self.control_slider.value
            if self.control_select.value == "Train" and len(self.net.dataset.train_targets) > 0:
                self.total_text.value = "of %s" % len(self.net.dataset.train_inputs)
                if self.net.model is None:
                    return
                if not dynamic_pictures_check():
                    self.regenerate(inputs=self.net.dataset.train_inputs[self.control_slider.value],
                                    targets=self.net.dataset.train_targets[self.control_slider.value])
                    return
                output = self.net.propagate(self.net.dataset.train_inputs[self.control_slider.value],
                                            class_id=self.class_id, update_pictures=True)
                if self.feature_bank.value in self.net.layer_dict.keys():
                    self.net.propagate_to_features(self.feature_bank.value, self.net.dataset.train_inputs[self.control_slider.value],
                                                   cols=self.feature_columns.value, scale=self.feature_scale.value, html=False)
                if self.net.config["show_targets"]:
                    if len(self.net.output_bank_order) == 1: ## FIXME: use minmax of output bank
                        self.net.display_component([self.net.dataset.train_targets[self.control_slider.value]],
                                                   "targets",
                                                   class_id=self.class_id,
                                                   minmax=(-1, 1))
                    else:
                        self.net.display_component(self.net.dataset.train_targets[self.control_slider.value],
                                                   "targets",
                                                   class_id=self.class_id,
                                                   minmax=(-1, 1))
                if self.net.config["show_errors"]: ## minmax is error
                    if len(self.net.output_bank_order) == 1:
                        errors = np.array(output) - np.array(self.net.dataset.train_targets[self.control_slider.value])
                        self.net.display_component([errors.tolist()],
                                                   "errors",
                                                   class_id=self.class_id,
                                                   minmax=(-1, 1))
                    else:
                        errors = []
                        for bank in range(len(self.net.output_bank_order)):
                            errors.append( np.array(output[bank]) - np.array(self.net.dataset.train_targets[self.control_slider.value][bank]))
                        self.net.display_component(errors, "errors",  class_id=self.class_id, minmax=(-1, 1))
            elif self.control_select.value == "Test" and len(self.net.dataset.test_targets) > 0:
                self.total_text.value = "of %s" % len(self.net.dataset.test_inputs)
                if self.net.model is None:
                    return
                if not dynamic_pictures_check():
                    self.regenerate(inputs=self.net.dataset.test_inputs[self.control_slider.value],
                                    targets=self.net.dataset.test_targets[self.control_slider.value])
                    return
                output = self.net.propagate(self.net.dataset.test_inputs[self.control_slider.value],
                                            class_id=self.class_id, update_pictures=True)
                if self.feature_bank.value in self.net.layer_dict.keys():
                    self.net.propagate_to_features(self.feature_bank.value, self.net.dataset.test_inputs[self.control_slider.value],
                                               cols=self.feature_columns.value, scale=self.feature_scale.value, html=False)
                if self.net.config["show_targets"]: ## FIXME: use minmax of output bank
                    self.net.display_component([self.net.dataset.test_targets[self.control_slider.value]],
                                               "targets",
                                               class_id=self.class_id,
                                               minmax=(-1, 1))
                if self.net.config["show_errors"]: ## minmax is error
                    if len(self.net.output_bank_order) == 1:
                        errors = np.array(output) - np.array(self.net.dataset.test_targets[self.control_slider.value])
                        self.net.display_component([errors.tolist()],
                                                   "errors",
                                                   class_id=self.class_id,
                                                   minmax=(-1, 1))
                    else:
                        errors = []
                        for bank in range(len(self.net.output_bank_order)):
                            errors.append( np.array(output[bank]) - np.array(self.net.dataset.test_targets[self.control_slider.value][bank]))
                        self.net.display_component(errors, "errors", class_id=self.class_id, minmax=(-1, 1))

    def toggle_play(self, button):
        ## toggle
        if self.button_play.description == "Play":
            self.button_play.description = "Stop"
            self.button_play.icon = "pause"
            self.player.resume()
        else:
            self.button_play.description = "Play"
            self.button_play.icon = "play"
            self.player.pause()

    def prop_one(self, button=None):
        self.update_slider_control({"name": "value"})

    def regenerate(self, button=None, inputs=None, targets=None):
        ## Protection when deleting object on shutdown:
        if isinstance(button, dict) and 'new' in button and button['new'] is None:
            return
        ## Update the config:
        self.net.config["dashboard.features.bank"] = self.feature_bank.value
        self.net.config["dashboard.features.columns"] = self.feature_columns.value
        self.net.config["dashboard.features.scale"] = self.feature_scale.value
        inputs = inputs if inputs is not None else self.get_current_input()
        targets = targets if targets is not None else self.get_current_targets()
        features = None
        if self.feature_bank.value in self.net.layer_dict.keys() and inputs is not None:
            if self.net.model is not None:
                features = self.net.propagate_to_features(self.feature_bank.value, inputs,
                                                          cols=self.feature_columns.value,
                                                          scale=self.feature_scale.value, display=False)
        svg = """<p style="text-align:center">%s</p>""" % (self.net.to_svg(
            inputs=inputs,
            targets=targets,
            class_id=self.class_id,
            highlights={self.feature_bank.value: {
                "border_color": "orange",
                "border_width": 30,
            }}))
        if inputs is not None and features is not None:
            html_horizontal = """
<table align="center" style="width: 100%%;">
 <tr>
  <td valign="top" style="width: 50%%;">%s</td>
  <td valign="top" align="center" style="width: 50%%;"><p style="text-align:center"><b>%s</b></p>%s</td>
</tr>
</table>"""
            html_vertical = """
<table align="center" style="width: 100%%;">
 <tr>
  <td valign="top">%s</td>
</tr>
<tr>
  <td valign="top" align="center"><p style="text-align:center"><b>%s</b></p>%s</td>
</tr>
</table>"""
            self.net_svg.value = (html_vertical if self.net.config["svg_rotate"] else html_horizontal) % (
                svg, "%s details" % self.feature_bank.value, features)
        else:
            self.net_svg.value = svg

    def make_colormap_image(self, colormap_name):
        from .layers import Layer
        if not colormap_name:
            colormap_name = get_colormap()
        layer = Layer("Colormap", 100)
        minmax = layer.get_act_minmax()
        image = layer.make_image(np.arange(minmax[0], minmax[1], .01),
                                 colormap_name,
                                 {"pixels_per_unit": 1,
                                  "svg_rotate": self.net.config["svg_rotate"]}).resize((300, 25))
        return image

    def set_attr(self, obj, attr, value):
        if value not in [{}, None]: ## value is None when shutting down
            if isinstance(value, dict):
                value = value["value"]
            if isinstance(obj, dict):
                obj[attr] = value
            else:
                setattr(obj, attr, value)
            ## was crashing on Widgets.__del__, if get_ipython() no longer existed
            self.regenerate()

    def make_controls(self):
        layout = Layout(width='100%', height="100%")
        button_begin = Button(icon="fast-backward", layout=layout)
        button_prev = Button(icon="backward", layout=layout)
        button_next = Button(icon="forward", layout=layout)
        button_end = Button(icon="fast-forward", layout=layout)
        #button_prop = Button(description="Propagate", layout=Layout(width='100%'))
        #button_train = Button(description="Train", layout=Layout(width='100%'))
        self.button_play = Button(icon="play", description="Play", layout=layout)
        step_down = Button(icon="sort-down", layout=Layout(width="95%", height="100%"))
        step_up = Button(icon="sort-up", layout=Layout(width="95%", height="100%"))
        up_down = HBox([step_down, step_up], layout=Layout(width="100%", height="100%"))
        refresh_button = Button(icon="refresh", layout=Layout(width="25%", height="100%"))

        self.position_text = IntText(value=0, layout=layout)

        self.control_buttons = HBox([
            button_begin,
            button_prev,
            #button_train,
            self.position_text,
            button_next,
            button_end,
            self.button_play,
            up_down,
            refresh_button
        ], layout=Layout(width='100%', height="100%"))
        length = (len(self.net.dataset.train_inputs) - 1) if len(self.net.dataset.train_inputs) > 0 else 0
        self.control_slider = IntSlider(description="Dataset index",
                                   continuous_update=False,
                                   min=0,
                                   max=max(length, 0),
                                   value=0,
                                   layout=Layout(width='100%'))
        if self.net.config["dashboard.dataset"] == "Train":
            length = len(self.net.dataset.train_inputs)
        else:
            length = len(self.net.dataset.test_inputs)
        self.total_text = Label(value="of %s" % length, layout=Layout(width="100px"))
        self.zoom_slider = FloatSlider(description="Zoom",
                                       continuous_update=False,
                                       min=0, max=1.0,
                                       style={"description_width": 'initial'},
                                       layout=Layout(width="65%"),
                                       value=self.net.config["svg_scale"] if self.net.config["svg_scale"] is not None else 0.5)

        ## Hook them up:
        button_begin.on_click(lambda button: self.goto("begin"))
        button_end.on_click(lambda button: self.goto("end"))
        button_next.on_click(lambda button: self.goto("next"))
        button_prev.on_click(lambda button: self.goto("prev"))
        self.button_play.on_click(self.toggle_play)
        self.control_slider.observe(self.update_slider_control, names='value')
        refresh_button.on_click(lambda widget: (self.update_control_slider(),
                                                self.output.clear_output(),
                                                self.regenerate()))
        step_down.on_click(lambda widget: self.move_step("down"))
        step_up.on_click(lambda widget: self.move_step("up"))
        self.zoom_slider.observe(self.update_zoom_slider, names='value')
        self.position_text.observe(self.update_position_text, names='value')
        # Put them together:
        controls = VBox([HBox([self.control_slider, self.total_text], layout=Layout(height="40px")),
                         self.control_buttons], layout=Layout(width='100%'))

        #net_page = VBox([control, self.net_svg], layout=Layout(width='95%'))
        controls.on_displayed(lambda widget: self.regenerate())
        return controls

    def move_step(self, direction):
        """
        Move the layer stepper up/down through network
        """
        options = [""] + [layer.name for layer in self.net.layers]
        index = options.index(self.feature_bank.value)
        if direction == "up":
            new_index = (index + 1) % len(options)
        else: ## down
            new_index = (index - 1) % len(options)
        self.feature_bank.value = options[new_index]
        self.regenerate()

    def make_config(self):
        layout = Layout()
        style = {"description_width": "initial"}
        checkbox1 = Checkbox(description="Show Targets", value=self.net.config["show_targets"],
                             layout=layout, style=style)
        checkbox1.observe(lambda change: self.set_attr(self.net.config, "show_targets", change["new"]), names='value')
        checkbox2 = Checkbox(description="Errors", value=self.net.config["show_errors"],
                             layout=layout, style=style)
        checkbox2.observe(lambda change: self.set_attr(self.net.config, "show_errors", change["new"]), names='value')

        hspace = IntText(value=self.net.config["hspace"], description="Horizontal space between banks:",
                         style=style, layout=layout)
        hspace.observe(lambda change: self.set_attr(self.net.config, "hspace", change["new"]), names='value')
        vspace = IntText(value=self.net.config["vspace"], description="Vertical space between layers:",
                         style=style, layout=layout)
        vspace.observe(lambda change: self.set_attr(self.net.config, "vspace", change["new"]), names='value')
        self.feature_bank = Select(description="Details:", value=self.net.config["dashboard.features.bank"],
                              options=[""] + [layer.name for layer in self.net.layers],
                              rows=1)
        self.feature_bank.observe(self.regenerate, names='value')
        self.control_select = Select(
            options=['Test', 'Train'],
            value=self.net.config["dashboard.dataset"],
            description='Dataset:',
            rows=1
        )
        self.control_select.observe(self.change_select, names='value')
        column1 = [self.control_select,
                   self.zoom_slider,
                   hspace,
                   vspace,
                   HBox([checkbox1, checkbox2]),
                   self.feature_bank,
                   self.feature_columns,
                   self.feature_scale
        ]
        ## Make layer selectable, and update-able:
        column2 = []
        layer = self.net.layers[-1]
        self.layer_select = Select(description="Layer:", value=layer.name,
                                   options=[layer.name for layer in
                                            self.net.layers],
                                   rows=1)
        self.layer_select.observe(self.update_layer_selection, names='value')
        column2.append(self.layer_select)
        self.layer_visible_checkbox = Checkbox(description="Visible", value=layer.visible, layout=layout)
        self.layer_visible_checkbox.observe(self.update_layer, names='value')
        column2.append(self.layer_visible_checkbox)
        self.layer_colormap = Select(description="Colormap:",
                                     options=[""] + AVAILABLE_COLORMAPS,
                                     value=layer.colormap if layer.colormap is not None else "", layout=layout, rows=1)
        self.layer_colormap_image = HTML(value="""<img src="%s"/>""" % self.net._image_to_uri(self.make_colormap_image(layer.colormap)))
        self.layer_colormap.observe(self.update_layer, names='value')
        column2.append(self.layer_colormap)
        column2.append(self.layer_colormap_image)
        ## get dynamic minmax; if you change it it will set it in layer as override:
        minmax = layer.get_act_minmax()
        self.layer_mindim = FloatText(description="Leftmost color maps to:", value=minmax[0], style=style)
        self.layer_maxdim = FloatText(description="Rightmost color maps to:", value=minmax[1], style=style)
        self.layer_mindim.observe(self.update_layer, names='value')
        self.layer_maxdim.observe(self.update_layer, names='value')
        column2.append(self.layer_mindim)
        column2.append(self.layer_maxdim)
        output_shape = layer.get_output_shape()
        self.layer_feature = IntText(value=layer.feature, description="Feature to show:", style=style)
        self.svg_rotate = Checkbox(description="Rotate", value=layer.visible, layout=layout)
        self.layer_feature.observe(self.update_layer, names='value')
        column2.append(self.layer_feature)
        self.svg_rotate = Checkbox(description="Rotate network",
                                   value=self.net.config["svg_rotate"],
                                   style={"description_width": 'initial'},
                                   layout=Layout(width="52%"))
        self.svg_rotate.observe(lambda change: self.set_attr(self.net.config, "svg_rotate", change["new"]), names='value')
        self.save_config_button = Button(icon="save", layout=Layout(width="10%"))
        self.save_config_button.on_click(self.save_config)
        column2.append(HBox([self.svg_rotate, self.save_config_button]))
        config_children = HBox([VBox(column1, layout=Layout(width="100%")),
                                VBox(column2, layout=Layout(width="100%"))])
        accordion = Accordion(children=[config_children])
        accordion.set_title(0, self.net.name)
        accordion.selected_index = None
        return accordion

    def save_config(self, widget=None):
        self.net.save_config()

    def update_layer(self, change):
        """
        Update the layer object, and redisplay.
        """
        if self._ignore_layer_updates:
            return
        ## The rest indicates a change to a display variable.
        ## We need to save the value in the layer, and regenerate
        ## the display.
        # Get the layer:
        layer = self.net[self.layer_select.value]
        # Save the changed value in the layer:
        layer.feature = self.layer_feature.value
        layer.visible = self.layer_visible_checkbox.value
        ## These three, dealing with colors of activations,
        ## can be done with a prop_one():
        if "color" in change["owner"].description.lower():
            ## Matches: Colormap, lefmost color, rightmost color
            ## overriding dynamic minmax!
            layer.minmax = (self.layer_mindim.value, self.layer_maxdim.value)
            layer.minmax = (self.layer_mindim.value, self.layer_maxdim.value)
            layer.colormap = self.layer_colormap.value if self.layer_colormap.value else None
            self.layer_colormap_image.value = """<img src="%s"/>""" % self.net._image_to_uri(self.make_colormap_image(layer.colormap))
            self.prop_one()
        else:
            self.regenerate()

    def update_layer_selection(self, change):
        """
        Just update the widgets; don't redraw anything.
        """
        ## No need to redisplay anything
        self._ignore_layer_updates = True
        ## First, get the new layer selected:
        layer = self.net[self.layer_select.value]
        ## Now, let's update all of the values without updating:
        self.layer_visible_checkbox.value = layer.visible
        self.layer_colormap.value = layer.colormap if layer.colormap != "" else ""
        self.layer_colormap_image.value = """<img src="%s"/>""" % self.net._image_to_uri(self.make_colormap_image(layer.colormap))
        minmax = layer.get_act_minmax()
        self.layer_mindim.value = minmax[0]
        self.layer_maxdim.value = minmax[1]
        self.layer_feature.value = layer.feature
        self._ignore_layer_updates = False
Exemple #36
0
class SequenceViewer(VBox):
    """
    SequenceViewer

    Arguments:
        title (str) - Title of sequence
        function (callable) - takes an index 0 to length - 1. Function should
            a displayable or list of displayables
        length (int) - total number of frames in sequence
        play_rate (float) - seconds to wait between frames when auto-playing.
            Optional. Default is 0.5 seconds.

    >>> def function(index):
    ...     return [None]
    >>> sv = SequenceViewer("Title", function, 10)
    >>> ## Do this manually for testing:
    >>> sv.initialize()
    None
    >>> ## Testing:
    >>> class Dummy:
    ...     def update(self, result):
    ...         return result
    >>> sv.displayers = [Dummy()]
    >>> print("Testing"); sv.goto("begin") # doctest: +ELLIPSIS
    Testing...
    >>> print("Testing"); sv.goto("end") # doctest: +ELLIPSIS
    Testing...
    >>> print("Testing"); sv.goto("prev") # doctest: +ELLIPSIS
    Testing...
    >>> print("Testing"); sv.goto("next") # doctest: +ELLIPSIS
    Testing...

    """
    def __init__(self, title, function, length, play_rate=0.5):
        self.player = _Player(self, play_rate)
        self.player.start()
        self.title = title
        self.function = function
        self.length = length
        self.output = Output()
        self.position_text = IntText(value=0, layout=Layout(width="100%"))
        self.total_text = Label(value="of %s" % self.length, layout=Layout(width="100px"))
        controls = self.make_controls()
        super().__init__([controls, self.output])

    def goto(self, position):
        #### Position it:
        if position == "begin":
            self.control_slider.value = 0
        elif position == "end":
            self.control_slider.value = self.length - 1
        elif position == "prev":
            if self.control_slider.value - 1 < 0:
                self.control_slider.value = self.length - 1 # wrap around
            else:
                self.control_slider.value = max(self.control_slider.value - 1, 0)
        elif position == "next":
            if self.control_slider.value + 1 > self.length - 1:
                self.control_slider.value = 0 # wrap around
            else:
                self.control_slider.value = min(self.control_slider.value + 1, self.length - 1)
        elif isinstance(position, int):
            self.control_slider.value = position
        self.position_text.value = self.control_slider.value

    def toggle_play(self, button):
        ## toggle
        if self.button_play.description == "Play":
            self.button_play.description = "Stop"
            self.button_play.icon = "pause"
            self.player.resume()
        else:
            self.button_play.description = "Play"
            self.button_play.icon = "play"
            self.player.pause()

    def make_controls(self):
        button_begin = Button(icon="fast-backward", layout=Layout(width='100%'))
        button_prev = Button(icon="backward", layout=Layout(width='100%'))
        button_next = Button(icon="forward", layout=Layout(width='100%'))
        button_end = Button(icon="fast-forward", layout=Layout(width='100%'))
        self.button_play = Button(icon="play", description="Play", layout=Layout(width="100%"))
        self.control_buttons = HBox([
            button_begin,
            button_prev,
            self.position_text,
            button_next,
            button_end,
            self.button_play,
        ], layout=Layout(width='100%', height="50px"))
        self.control_slider = IntSlider(description=self.title,
                                        continuous_update=False,
                                        min=0,
                                        max=max(self.length - 1, 0),
                                        value=0,
                                        style={"description_width": 'initial'},
                                        layout=Layout(width='100%'))
        ## Hook them up:
        button_begin.on_click(lambda button: self.goto("begin"))
        button_end.on_click(lambda button: self.goto("end"))
        button_next.on_click(lambda button: self.goto("next"))
        button_prev.on_click(lambda button: self.goto("prev"))
        self.button_play.on_click(self.toggle_play)
        self.control_slider.observe(self.update_slider_control, names='value')
        controls = VBox([HBox([self.control_slider, self.total_text], layout=Layout(height="40px")),
                         self.control_buttons], layout=Layout(width='100%'))
        controls.on_displayed(lambda widget: self.initialize())
        return controls

    def initialize(self):
        results = self.function(self.control_slider.value)
        try:
            results = list(results)
        except:
            results = [results]
        self.displayers = [display(x, display_id=True) for x in results]

    def update_slider_control(self, change):
        if change["name"] == "value":
            self.position_text.value = self.control_slider.value
            self.output.clear_output(wait=True)
            results = self.function(self.control_slider.value)
            try:
                results = list(results)
            except:
                results = [results]
            for i in range(len(self.displayers)):
                self.displayers[i].update(results[i])