Exemple #1
0
    def update(self):
        scores = self.pred_scores[self.vis_image_index]
        im = self.dataset[self.vis_image_index][0]  # fastai Image object

        _, sort_order = self._list_sort(scores, reverse=True)
        pred_labels_str = ""
        for i in sort_order:
            pred_labels_str += f"{self.labels[i]} ({scores[i]:3.2f})\n"
        self.w_pred_labels.value = str(pred_labels_str)

        self.w_image_header.value = f"Image index: {self.vis_image_index}"

        self.w_img.value = im._repr_png_()
        # Fix the width of the image widget and adjust the height
        self.w_img.layout.height = (
            f"{int(self.IM_WIDTH * (im.size[1]/im.size[0]))}px")

        self.w_gt_label.value = str(
            self.labels[self.dataset[self.vis_image_index][1]])

        self.w_filename.value = str(
            self.dataset.items[self.vis_image_index].name)
        self.w_path.value = str(
            self.dataset.items[self.vis_image_index].parent)
        bqpyplot.clear()
        bqpyplot.bar(
            self.labels,
            scores,
            align="center",
            alpha=1.0,
            color=np.abs(scores),
            scales={"color": bqplot.ColorScale(scheme="Blues", min=0)},
        )
Exemple #2
0
    def init_plot(self):
        self.xscale = bq.LinearScale()
        self.yscale = bq.LinearScale()
        self.zscale = bq.ColorScale(scheme='Reds')
        self.heat = bq.HeatMap(
            x=self.x,
            y=self.y,
            color=self.z,
            scales=dict(
                x=self.xscale,
                y=self.yscale,
                color=self.zscale
            )
        )
        self.xax = bq.Axis(
            scale=self.xscale,
            label=self.labels['x']
        )
        self.yax = bq.Axis(
            scale=self.yscale,
            label=self.labels['y'],
            orientation='vertical'
        )
        self.zax = bq.Axis(scale=self.zscale)

        super().__init__(
            marks=[self.heat],
            axes=[self.xax, self.yax, self.zax],
        )
Exemple #3
0
    def __init__(self, view, viewer_state, layer, layer_state):
        super(BqplotImageLayerArtist, self).__init__(layer)
        self.view = view
        self.state = layer_state or self._layer_state_cls(
            viewer_state=viewer_state, layer=self.layer)
        self._viewer_state = viewer_state
        if self.state not in self._viewer_state.layers:
            self._viewer_state.layers.append(self.state)

        # self._update_compatibility()

        self.scale_image = bqplot.ColorScale()
        self.scales = {
            'x': self.view.scale_x,
            'y': self.view.scale_y,
            'image': self.scale_image
        }
        self.image_mark = bqplot.Image(image=[[1, 2], [3, 4]],
                                       scales=self.scales)
        self.color_axis = bqplot.ColorAxis(side='right',
                                           scale=self.scale_image,
                                           orientation='vertical')
        self.view.figure.axes = list(self.view.figure.axes) + [self.color_axis]

        self.view.figure.marks = list(
            self.view.figure.marks) + [self.image_mark]

        viewer_state.add_callback('x_att', self._update_xy_att)
        viewer_state.add_callback('y_att', self._update_xy_att)
Exemple #4
0
    def init_bq_fig(self):
        self.bq_xscale = bq.LinearScale()
        self.bq_yscale = bq.LinearScale()
        self.bq_colorscale = bq.ColorScale(min=-1, max=1)
        self.bq_xax = bq.Axis(scale=self.bq_xscale)
        self.bq_yax = bq.Axis(scale=self.bq_yscale, orientation='vertical')
        self.bq_colorax = bq.ColorAxis(scale=self.bq_colorscale)
        self.bq_heat = bq.HeatMap(
            x=self.x,
            y=self.z,
            color=zeros_like(self.cY),
            scales={
                'x': self.bq_xscale,
                'y': self.bq_yscale,
                'color': self.bq_colorscale
            }

        )
        self.bq_fig = bq.Figure(
            marks=[self.bq_heat],
            axes=[
                self.bq_xax,
                self.bq_yax,
                self.bq_colorax
            ]
        )
Exemple #5
0
 def __init__(self, scheme, count=None, **options):
     colors = self.palettes[scheme]
     super().__init__(scheme, count or len(colors))
     self.colors = self.mkpal(colors, self.count)
     self.opt = opt = getopt(options,
                             fig_title=self.scheme,
                             fig_width=960,
                             fig_height=150)
     data = np.arange(0, len(self.colors))
     cs = bq.ColorScale(colors=self.colors)
     hm = bq.HeatMap(color=np.array([data, data]), scales={"color": cs})
     self.figure = bq.Figure(marks=[hm],
                             layout=ipw.Layout(
                                 width="%spx" % opt.fig["width"],
                                 height="%spx" % opt.fig["height"]),
                             padding_x=0.0,
                             padding_y=0.0,
                             fig_margin={
                                 "top": 60,
                                 "bottom": 0,
                                 "left": 0,
                                 "right": 0
                             },
                             title=opt.fig["title"])
     self.vbox = ipw.VBox([self.figure, bq.Toolbar(figure=self.figure)])
Exemple #6
0
    def __init__(self, **kwargs):
        super(VizHeatmapBqplot, self).__init__(**kwargs)
        self.fig.padding_y = 0
        self.fig.fig_margin = {'bottom': 80, 'left': 60, 'right': 10, 'top': 60}

        grid = self.state.grid
        if self.state.grid_sliced is not None:
            grid = self.state.grid_sliced
        if self.normalize:
            grid = grid/grid.sum()
        self.color_scale = bqplot.ColorScale(scheme='Blues')
        self.color_axis = bqplot.ColorAxis(scale=self.color_scale, label='counts', scheme='Blues')
        self.fig.axes = self.fig.axes + [self.color_axis]
        self.scales = {'row': self.y_scale, 'column': self.x_scale, 'color': self.color_scale}
        # self.scales = {'row': bqplot.OrdinalScale(), 'column': bqplot.OrdinalScale(), 'color': self.color_scale}
        
        self.heatmap = bqplot.GridHeatMap(color=grid.T[:,::], scales=self.scales)
        self.update_heatmap()
        self.fig.marks = self.fig.marks + [self.heatmap]
        self.state.observe(self.update_heatmap, 'grid')
        widgets.dlink((self.state, 'x_expression'), (self.x_axis, 'label'))
        widgets.dlink((self.state, 'y_expression'), (self.y_axis, 'label'))
        @self.output.capture()
        # @vaex.jupyter.debounced(DEBOUNCE_SLICE)
        def on_bar_hover(bar, event):
#             print(event)
            #set_transparancy(event['data']['sub_index'], event['data']['index'])
            #print(event['data']['index'])
            self.state.y_slice = event['data']['row']
            self.state.x_slice = event['data']['column']
            self.set_transparancy()
            #print(viz_state.grid.sum())
        self.heatmap.on_hover(on_bar_hover)
    def __init__(self, view, viewer_state, layer, layer_state):
        super(BqplotScatterLayerArtist, self).__init__(layer)
        self.view = view
        self.state = layer_state or self._layer_state_cls(viewer_state=viewer_state,
                                                          layer=self.layer)
        self._viewer_state = viewer_state
        if self.state not in self._viewer_state.layers:
            self._viewer_state.layers.append(self.state)
        self.scale_size = bqplot.LinearScale()
        self.scale_color = bqplot.ColorScale()
        self.scale_size_quiver = bqplot.LinearScale(min=0, max=1)
        self.scale_rotation = bqplot.LinearScale(min=0, max=1)
        self.scales = dict(self.view.scales, size=self.scale_size, rotation=self.scale_rotation, color=self.scale_color)
        self.scales_quiver = dict(self.view.scales, size=self.scale_size_quiver, rotation=self.scale_rotation)
        self.scatter = bqplot.ScatterMega(scales=self.scales, x=[0, 1], y=[0, 1])
        self.quiver = bqplot.ScatterMega(scales=self.scales_quiver, x=[0, 1], y=[0, 1], visible=False, marker='arrow')
        self.view.figure.marks = list(self.view.figure.marks) + [self.scatter, self.quiver]
        link((self.state, 'color'), (self.scatter, 'colors'), lambda x: [x], lambda x: x[0])
        link((self.state, 'color'), (self.quiver, 'colors'), lambda x: [x], lambda x: x[0])
        self.scatter.observe(self._workaround_unselected_style, 'colors')
        self.quiver.observe(self._workaround_unselected_style, 'colors')

        on_change([(self.state, 'cmap_mode', 'cmap_att')])(self._on_change_cmap_mode_or_att)
        on_change([(self.state, 'cmap')])(self._on_change_cmap)
        link((self.state, 'cmap_vmin'), (self.scale_color, 'min'))
        link((self.state, 'cmap_vmax'), (self.scale_color, 'max'))

        on_change([(self.state, 'size', 'size_scaling', 'size_mode', 'size_vmin', 'size_vmax')])(self._update_size)

        viewer_state.add_callback('x_att', self._update_xy_att)
        viewer_state.add_callback('y_att', self._update_xy_att)
        self._update_size()
        # set initial values for the colormap
        self._on_change_cmap()
Exemple #8
0
    def update_ui(self):
        pred_label = self.pred_labels[self.vis_image_index]
        img_obj = self.dataset.images[self.vis_image_index]
        scores = self.pred_scores[self.vis_image_index]

        self.w_image_header.value = "Image index: {}".format(
            self.vis_image_index)
        self.w_img.value = wImread(img_obj, self.context)
        self.w_gt_label.value = self.dataset.get_labels_for_image(
            img_obj)[0].name
        self.w_pred_label.value = str(pred_label)
        self.w_pred_score.value = str(
            self.pred_scores[self.vis_image_index,
                             self.label_to_id[pred_label]])
        self.w_index.value = str(self.vis_image_index)
        self.w_filename.value = img_obj.name
        self.w_path.value = img_obj.storage_path
        bqPyplot.clear()
        bqPyplot.bar(
            self.labels,
            scores,
            align='center',
            alpha=1.0,
            color=np.abs(scores),
            scales={'color': bqplot.ColorScale(scheme='Blues', min=0)})
Exemple #9
0
 def gui_graph (self) :
     ncs = bq.ColorScale(colors=self.nodes_palette)
     graph = bq.Graph(node_data=self.node_data,
                      link_data=self.link_data,
                      link_type="line",
                      directed=self.opt.graph.directed,
                      color=self.nodes_color,
                      scales={"x": self._x_scale,
                              "y": self._y_scale,
                              "color": ncs},
                      x=self.nodes_x,
                      y=self.nodes_y)
     return graph
Exemple #10
0
 def gui_tips (self) :
     sc_r = bq.LinearScale(min=0, max=np.pi)
     sc_c = bq.ColorScale(colors=Palette.mkpal(["#000000", "#FFFFFF"]))
     tips = {}
     for shape in self._tips_shapes :
         for end in ("src", "dst") :
             edges = self.edges[self.edges["_shape_" + end] == shape]
             scatt = bq.Scatter(x=edges["_x_" + end],
                                y=edges["_y_" + end],
                                marker=shape,
                                rotation=edges["_angle_" + end],
                                color=edges["_color_" + end],
                                stroke="#000000",
                                scales={"x" : self._x_scale,
                                        "y" : self._y_scale,
                                        "color" : sc_c,
                                        "rotation" : sc_r,
                                })
             tips[end,shape] = scatt
     return tips
 def updateUI(self):
     predLabel = self.predLabels[self.visImageIndex]
     imgObj = self.dataset.images[self.visImageIndex]
     scores = self.predScores[self.visImageIndex]
     self.wImageHeader.value = "Image index: {}".format(self.visImageIndex)
     self.wImg.value = wImread(imgObj, self.imgOrigDir)
     self.wGtLabel.value = imgObj.label
     self.wPredLabel.value = str(self.lutId2Label[predLabel])
     self.wPredScore.value = str(self.predScores[self.visImageIndex,
                                                 predLabel])
     self.wIndex.value = str(self.visImageIndex)
     self.wFilename.value = imgObj.filename
     bqPyplot.clear()
     bqPyplot.bar(
         self.labels,
         scores,
         align='center',
         alpha=1.0,
         color=np.abs(scores),
         scales={'color': bqplot.ColorScale(scheme='Blues', min=0)})
Exemple #12
0
    def gui_marks (self) :
        sc_s = bq.LinearScale(min=5, max=10)
        sc_o = bq.LinearScale(min=0, max=1)
        sc_c = bq.ColorScale(colors=self.marks_palette)
        marks = {}
        for shape in self._marks_shapes :
            nodes = self.nodes[self.nodes["_marks_shape"] == shape]
            scatt = bq.Scatter(x=nodes["_marks_x"],
                               y=nodes["_marks_y"],
                               size=nodes["_marks_size"],
                               opacity=nodes["_marks_opacity"],
                               color=nodes["_marks_color"],
                               marker=shape,
                               stroke=self.opt.marks.stroke,
                               scales={"x" : self._x_scale,
                                       "y" : self._y_scale,
                                       "size" : sc_s,
                                       "opacity" : sc_o,
                                       "color" : sc_c})

            marks[shape] = scatt
        return marks
import pandas as pd
import bqplot
import us

names = [
    "date", "city", "state", "country", "shape", "duration_seconds",
    "duration_reported", "description", "report_date", "latitude", "longitude"
]

fn = "/srv/nbgrader/data/ufo-scrubbed-geocoded-time-standardized.csv",
ufo = pd.read_csv(fn, names=names, parse_dates=["date", "report_date"])

abbr_to_fits = us.states.mapping('abbr', 'fips')
ufo["fips"] = ufo["state"].apply(
    lambda a: int(abbr_to_fits.get(str(a).upper(), -1)))

map_styles = {
    'scales': {
        'projection': bqplot.AlbersUSA(),
        'color': bqplot.ColorScale(colors=["red", "blue"])
    },
    'color': fips_count.to_dict()
}
states_map = bqplot.Map(map_data=bqplot.topo_load('map_data/USStatesMap.json'),
                        **map_styles)
map_fig = bqplot.Figure(marks=[states_map], title='USA')
Exemple #14
0
def test_astro_image():
    data = np.zeros((2, 3))
    color_scale = bqplot.ColorScale()
    scale_x = bqplot.LinearScale()
    scale_y = bqplot.LinearScale()
    ImageGL(image=data, scales={'image': color_scale, 'x': scale_x, 'y': scale_y})
Exemple #15
0
    def _gen_series_tab(self):
        """Creates widgets for selecting timeseries data.
          - Dropdown to select column from dataframe.
          - Interactive bqplot with BrushIntervalSelector.
    
        Returns
        -------
        widget : tab content widget
        """
        scales = {
            'x': bqp.DateScale(),
            'y': bqp.LinearScale(),
            'color': bqp.ColorScale(scheme='oranges')
        }

        axes = [
            bqp.Axis(scale=scales['x'],
                     label='Date',
                     num_ticks=int(len(self._data.index) / 2)),
            bqp.Axis(scale=scales['y'], label='Value', orientation='vertical')
        ]

        mark = bqp.Lines(scales=scales)

        feature_selector = widgets.Dropdown(options=self._data.columns,
                                            description='Feature:')

        def feature_selection_callback(change):
            """Callback to update graph when new data has been selected
    
            Parameters
            ----------
            change : dict
                Widget and changed values.
            """
            self._selected_feature = change.new
            fig.title = f'Feature: {change.new}'
            series = self._data[change.new]
            mark.x = series.index
            mark.y = series.values

        # register callback for dropdown value-change events
        feature_selector.observe(feature_selection_callback, ['value'])

        def brush_sel_dt_callback(change):
            """Callback to update graph when new data has been selected
    
            Parameters
            ----------
            change : dict
                Widget and changed values.
            """
            tstamps = selector.selected
            if isinstance(tstamps, np.ndarray):
                tstamps = tstamps.tolist()
            if not selector.brushing and tstamps:
                # extract year and month from timestamp string: e.g. 2000-03-11T06:51:50.089000 -> 2000-03
                dates = [
                    pd.to_datetime(re.split(r'-\d\dT', str(ts))[0])
                    for ts in tstamps
                ]
                self._selected_dates = dates

        selector = bqpi.BrushIntervalSelector(scale=scales['x'], color='blue')
        # register callback for BrushIntervalSelector brushing events
        selector.observe(brush_sel_dt_callback, ['brushing'])

        fig = bqp.Figure(marks=[mark],
                         axes=axes,
                         interaction=selector,
                         layout=widgets.Layout(width='880px', height='380px'),
                         animation_duration=1000)

        def reset_btn_click(b):
            """Reset selector and update instance properties accordingly.
    
            Parameters
            ----------
            b : Button
                Button instance.
            """
            selector.reset()
            self.reset()

        reset_btn = widgets.Button(description='reset')
        reset_btn.on_click(reset_btn_click)

        return widgets.VBox(children=[
            widgets.HBox(children=[feature_selector, reset_btn]), fig
        ])
Exemple #16
0
    def __init__(self, view, viewer_state, layer_state=None, layer=None):

        super(BqplotScatterLayerArtist, self).__init__(viewer_state,
                                                       layer_state=layer_state,
                                                       layer=layer)

        self.view = view

        self.scale_size = bqplot.LinearScale()
        self.scale_color = bqplot.ColorScale()
        self.scale_size_quiver = bqplot.LinearScale(min=0, max=1)
        self.scale_rotation = bqplot.LinearScale(min=0, max=1)
        self.scales = dict(self.view.scales,
                           size=self.scale_size,
                           rotation=self.scale_rotation,
                           color=self.scale_color)
        self.scale_image = bqplot.ColorScale()
        self.scales_quiver = dict(self.view.scales,
                                  size=self.scale_size_quiver,
                                  rotation=self.scale_rotation)
        self.scales_image = dict(self.view.scales, image=self.scale_image)
        self.scatter = bqplot.ScatterGL(scales=self.scales, x=[0, 1], y=[0, 1])
        self.quiver = bqplot.ScatterGL(scales=self.scales_quiver,
                                       x=[0, 1],
                                       y=[0, 1],
                                       visible=False,
                                       marker='arrow')

        self.counts = None
        self.image = AstroImage(scales=self.scales_image)
        on_change([(self.state, 'density_map')])(self._on_change_density_map)
        on_change([(self.state, 'bins')])(self._update_scatter)
        self._viewer_state.add_global_callback(self._update_scatter)

        self.view.figure.marks = list(
            self.view.figure.marks) + [self.image, self.scatter, self.quiver]
        dlink((self.state, 'color'), (self.scatter, 'colors'), lambda x: [x])
        dlink((self.state, 'color'), (self.quiver, 'colors'), lambda x: [x])
        self.scatter.observe(self._workaround_unselected_style, 'colors')
        self.quiver.observe(self._workaround_unselected_style, 'colors')

        on_change([(self.state, 'cmap_mode', 'cmap_att')
                   ])(self._on_change_cmap_mode_or_att)
        on_change([(self.state, 'cmap')])(self._on_change_cmap)
        dlink((self.state, 'cmap_vmin'), (self.scale_color, 'min'),
              float_or_none)
        dlink((self.state, 'cmap_vmax'), (self.scale_color, 'max'),
              float_or_none)

        on_change([(self.state, 'size', 'size_scaling', 'size_mode',
                    'size_vmin', 'size_vmax')])(self._update_size)

        viewer_state.add_callback('x_att', self._update_xy_att)
        viewer_state.add_callback('y_att', self._update_xy_att)
        self._update_size()
        # set initial values for the colormap
        self._on_change_cmap()

        self.state.add_callback('visible', self._update_visibility)
        self.state.add_callback('vector_visible', self._update_visibility)
        self.state.add_callback('density_map', self._update_visibility)

        dlink((self.state, 'visible'), (self.scatter, 'visible'))
        dlink((self.state, 'visible'), (self.image, 'visible'))

        dlink((self.state, 'alpha'), (self.scatter, 'default_opacities'),
              lambda x: [x])
        dlink((self.state, 'alpha'), (self.quiver, 'default_opacities'),
              lambda x: [x])
        dlink((self.state, 'alpha'), (self.image, 'opacity'))

        on_change([(self.state, 'vector_visible', 'vx_att', 'vy_att')
                   ])(self._update_quiver)
        dlink((self.state, 'vector_visible'), (self.quiver, 'visible'))
Exemple #17
0
class NetworkViewBase(ipyw.VBox):
    """An interactive, navigable display of the network.

    The NetworkViewBase class simply generates an interactive figure,
    without ipywidget buttons and dropdown menus. The NetworkModel extends
    this class, adding widget controls.

    Parameters
    ----------
    case : PSSTCase
        An instance of a PSST case.
    model : NetworkModel
        An instance of NetworkModel can be passed instead
        of a case. (Should not pass both.)

    Attributes
    ----------
    model : NetworkModel
        An instance of NetworkModel, containing state information for network.
    show_gen : Bool
        Display the points representing generators and connected lines.
    show_load : Bool
        Display the points representing loads and connected lines.
    show_bus_names : Bool
        Display names next to buses.
    show_gen_names : Bool
        Display names next to generators.
    show_load_names : Bool
        Display names next to loads.
    """

    model = t.Instance(NetworkModel)
    show_gen = t.Bool(default_value=True)
    show_load = t.Bool(default_value=True)

    show_background_lines = t.Bool(default_value=True)
    show_bus_names = t.Bool(default_value=True)
    show_gen_names = t.Bool(default_value=True)
    show_load_names = t.Bool(default_value=True)

    def __init__(self, case=None, model=None, *args, **kwargs):
        super(NetworkViewBase, self).__init__(*args, **kwargs)

        ##################
        # Load and Store Model
        ##################
        if model and case:
            warnings.warn(
                'You should pass a case OR a model, not both. The case argument you passed is being ignored.'
            )
        if not model:
            self.model = NetworkModel(case)
        else:
            self.model = model

        ##################
        # Scale Marks
        ##################
        self._scale_x = bq.LinearScale(min=self.model.x_min_view,
                                       max=self.model.x_max_view)
        self._scale_y = bq.LinearScale(min=self.model.y_min_view,
                                       max=self.model.y_max_view)
        self._scales = {
            'x': self._scale_x,
            'y': self._scale_y,
        }

        # Temp/experimental.
        self._my_scales = {
            'x': self._scale_x,
            'y': self._scale_y,
            'color': bq.ColorScale(colors=['Red', 'Green']),
        }

        ##################
        # Scatter Marks
        ##################
        # Tooltip
        scatter_tooltip = bq.Tooltip(fields=['name'])

        # Create Bus Scatter
        self._bus_scatter = bq.Scatter(
            x=self.model.bus_x_vals,
            y=self.model.bus_y_vals,
            scales=self._scales,
            names=self.model.bus_names,
            marker='rectangle',
            default_size=180,
            colors=[style.graph_main_1],
            default_opacities=[0.6],
            selected_style={
                'opacity': 0.8,
                'fill': style.graph_selected_1,
                'stroke': style.graph_accent_1
            },
            selected=self._get_indices_view_buses(),
            tooltip=scatter_tooltip,
        )
        # Create Gen Scatter
        self._gen_scatter = bq.Scatter(
            x=self.model.gen_x_vals,
            y=self.model.gen_y_vals,
            scales=self._scales,
            names=self.model.gen_names,
            marker='circle',
            default_size=150,
            colors=[style.graph_main_2],
            default_opacities=[0.6],
            selected_style={
                'opacity': 0.8,
                'fill': style.graph_selected_2,
                'stroke': style.graph_accent_2
            },
            tooltip=scatter_tooltip,
        )
        # Create Load Scatter
        self._load_scatter = bq.Scatter(
            x=self.model.load_x_vals,
            y=self.model.load_y_vals,
            scales=self._scales,
            names=self.model.load_names,
            marker='triangle-up',
            default_size=140,
            colors=[style.graph_main_3],
            default_opacities=[0.6],
            selected_style={
                'opacity': 0.8,
                'fill': style.graph_selected_3,
                'stroke': style.graph_accent_3
            },
            tooltip=scatter_tooltip,
        )

        ##################
        # Line Marks
        ##################

        # import numpy as np
        # self.vals = np.random.randint(0, 2, size=len(self.model.bus_x_edges))

        # Create Bus Lines
        self._bus_lines = bq.Lines(
            x=self.model.bus_x_edges,
            y=self.model.bus_y_edges,
            scales=self._scales,
            # colors=vals.
            colors=[style.graph_line_1],
            stroke_width=2,
            line_style='solid',
            opacities=[0.8],
        )
        # Create Gen Lines
        self._gen_lines = bq.Lines(
            x=self.model.gen_x_edges,
            y=self.model.gen_y_edges,
            scales=self._scales,
            # colors=['black'],
            colors=[style.graph_line_2],
            stroke_width=1.5,
            line_style='solid',
            opacities=[0.8])
        # Create Load Lines
        self._load_lines = bq.Lines(
            x=self.model.load_x_edges,
            y=self.model.load_y_edges,
            scales=self._scales,
            # colors=['black'],
            colors=[style.graph_line_3],
            stroke_width=1.5,
            line_style='solid',
            opacities=[0.8],
        )
        # All lines, in background
        self._background_lines = bq.Lines(
            x=self.model.x_edges,
            y=self.model.y_edges,
            scales=self._scales,
            colors=['gray'],
            stroke_width=1,
            line_style='dotted',
            opacities=[0.05],
            marker='circle',
            marker_size=30,
        )

        ##################
        # Bqplot Figure
        ##################
        self._all_marks = OrderedDict({
            'background_lines': self._background_lines,
            'bus_lines': self._bus_lines,
            'gen_lines': self._gen_lines,
            'load_lines': self._load_lines,
            'bus_scatter': self._bus_scatter,
            'gen_scatter': self._gen_scatter,
            'load_scatter': self._load_scatter,
        })

        fig_margin = {'top': 0, 'bottom': 0, 'left': 0, 'right': 0}
        self._figure = bq.Figure(
            marks=list(self._all_marks.values()),
            animation_duration=0,
            fig_margin=fig_margin,
        )

        # Set as children of VBox
        self.children = [self._figure]

        # Set defaults, triggering callback functions (setting proper children)
        self.show_background_lines = False
        self.show_gen_names = False
        self.show_load_names = False

        ##################
        # Link Traits
        ##################
        # Link Scales
        t.link((self.model, 'x_min_view'), (self._scale_x, 'min'))
        t.link((self.model, 'x_max_view'), (self._scale_x, 'max'))
        t.link((self.model, 'y_min_view'), (self._scale_y, 'min'))
        t.link((self.model, 'y_max_view'), (self._scale_y, 'max'))

        # Link Bus Scatter
        t.link((self.model, 'bus_x_vals'), (self._bus_scatter, 'x'))
        t.link((self.model, 'bus_y_vals'), (self._bus_scatter, 'y'))
        t.link((self.model, 'bus_names'), (self._bus_scatter, 'names'))

        # Link Gen Scatter
        t.link((self.model, 'gen_x_vals'), (self._gen_scatter, 'x'))
        t.link((self.model, 'gen_y_vals'), (self._gen_scatter, 'y'))
        t.link((self.model, 'gen_names'), (self._gen_scatter, 'names'))

        # Link Load Scatter
        t.link((self.model, 'load_x_vals'), (self._load_scatter, 'x'))
        t.link((self.model, 'load_y_vals'), (self._load_scatter, 'y'))
        t.link((self.model, 'load_names'), (self._load_scatter, 'names'))

        # Link Bus Lines
        t.link((self.model, 'bus_x_edges'), (self._bus_lines, 'x'))
        t.link((self.model, 'bus_y_edges'), (self._bus_lines, 'y'))

        # Link Gen Lines
        t.link((self.model, 'gen_x_edges'), (self._gen_lines, 'x'))
        t.link((self.model, 'gen_y_edges'), (self._gen_lines, 'y'))

        # Link Load Lines
        t.link((self.model, 'load_x_edges'), (self._load_lines, 'x'))
        t.link((self.model, 'load_y_edges'), (self._load_lines, 'y'))

        # Link names to show
        t.link((self, 'show_bus_names'), (self._bus_scatter, 'display_names'))
        t.link((self, 'show_gen_names'), (self._gen_scatter, 'display_names'))
        t.link((self, 'show_load_names'),
               (self._load_scatter, 'display_names'))

        # Set callbacks for clicking a bus
        # Click -> updates `model.view_buses` -> updates `bus_scatter.selected`
        self._bus_scatter.on_element_click(self._callback_bus_clicked)
        self.model.observe(self._callback_view_buses_change,
                           names='view_buses')

        # Callbacks for clicking a load/gen node (Simply flashes selected)
        self._gen_scatter.on_element_click(self._callback_nonebus_clicked)
        self._load_scatter.on_element_click(self._callback_nonebus_clicked)