Example #1
0
class Plot(PlotObject):

    data_sources = List
    title = String("Bokeh Plot")

    x_range = Instance(DataRange1d, has_ref=True)
    y_range = Instance(DataRange1d, has_ref=True)

    # We shouldn't need to create mappers manually on the Python side
    #xmapper = Instance(LinearMapper)
    #ymapper = Instance(LinearMapper)
    #mapper = Instance(GridMapper)

    # A list of all renderers on this plot; this includes guides as well
    # as glyph renderers
    renderers = List(has_ref=True)
    tools = List(has_ref=True)

    # TODO: These don't appear in the CS source, but are created by mpl.py, so
    # I'm leaving them here for initial compatibility testing.
    axes = List(has_ref=True)

    # TODO: How do we want to handle syncing of the different layers?
    # image = List
    # underlay = List
    # glyph = List
    # overlay = List
    # annotation = List

    height = Int(400)
    width = Int(400)

    background_fill = Color("white")
    border_fill = Color("white")
    canvas_width = Int(400)
    canvas_height = Int(400)
    outer_width = Int(400)
    outer_height = Int(400)
    border_top = Int(50)
    border_bottom = Int(50)
    border_left = Int(50)
    border_right = Int(50)
Example #2
0
class PointGlyph(XyGlyph):
    """A set of glyphs placed in x,y coordinates with the same attributes."""

    fill_color = Color(default=DEFAULT_PALETTE[1])
    fill_alpha = Override(default=0.7)
    marker = String(default='circle')
    size = Float(default=8)

    def __init__(self,
                 x=None,
                 y=None,
                 line_color=None,
                 fill_color=None,
                 marker=None,
                 size=None,
                 **kwargs):
        kwargs['x'] = x
        kwargs['y'] = y
        if line_color is not None:
            kwargs['line_color'] = line_color
        if fill_color is not None:
            kwargs['fill_color'] = fill_color
        if marker is not None:
            kwargs['marker'] = marker
        if size is not None:
            kwargs['size'] = size
        super(PointGlyph, self).__init__(**kwargs)
        self.setup()

    def get_glyph(self):
        return marker_types[self.marker]

    def build_renderers(self):
        glyph_type = self.get_glyph()
        glyph = glyph_type(x='x_values',
                           y='y_values',
                           line_color=self.line_color,
                           fill_color=self.fill_color,
                           size=self.size,
                           fill_alpha=self.fill_alpha,
                           line_alpha=self.line_alpha)
        yield GlyphRenderer(glyph=glyph)
Example #3
0
    def test_Color(self):
        prop = Color()

        self.assertTrue(prop.is_valid(None))
        self.assertFalse(prop.is_valid(False))
        self.assertFalse(prop.is_valid(True))
        self.assertFalse(prop.is_valid(0))
        self.assertFalse(prop.is_valid(1))
        self.assertFalse(prop.is_valid(0.0))
        self.assertFalse(prop.is_valid(1.0))
        self.assertFalse(prop.is_valid(1.0 + 1.0j))
        self.assertFalse(prop.is_valid(""))
        self.assertFalse(prop.is_valid(()))
        self.assertFalse(prop.is_valid([]))
        self.assertFalse(prop.is_valid({}))
        self.assertFalse(prop.is_valid(Foo()))

        self.assertTrue(prop.is_valid((0, 127, 255)))
        self.assertFalse(prop.is_valid((0, -127, 255)))
        self.assertFalse(prop.is_valid((0, 127)))
        self.assertFalse(prop.is_valid((0, 127, 1.0)))
        self.assertFalse(prop.is_valid((0, 127, 255, 255)))
        self.assertTrue(prop.is_valid((0, 127, 255, 1.0)))

        self.assertTrue(prop.is_valid("#00aaff"))
        self.assertTrue(prop.is_valid("#00AAFF"))
        self.assertTrue(prop.is_valid("#00AaFf"))
        self.assertFalse(prop.is_valid("00aaff"))
        self.assertFalse(prop.is_valid("00AAFF"))
        self.assertFalse(prop.is_valid("00AaFf"))
        self.assertFalse(prop.is_valid("#00AaFg"))
        self.assertFalse(prop.is_valid("#00AaFff"))

        self.assertTrue(prop.is_valid("blue"))
        self.assertFalse(prop.is_valid("BLUE"))
        self.assertFalse(prop.is_valid("foobar"))
Example #4
0
    def test_Color(self):
        prop = Color()

        self.assertTrue(prop.is_valid(None))
        self.assertFalse(prop.is_valid(False))
        self.assertFalse(prop.is_valid(True))
        self.assertFalse(prop.is_valid(0))
        self.assertFalse(prop.is_valid(1))
        self.assertFalse(prop.is_valid(0.0))
        self.assertFalse(prop.is_valid(1.0))
        self.assertFalse(prop.is_valid(1.0+1.0j))
        self.assertFalse(prop.is_valid(""))
        self.assertFalse(prop.is_valid(()))
        self.assertFalse(prop.is_valid([]))
        self.assertFalse(prop.is_valid({}))
        self.assertFalse(prop.is_valid(Foo()))

        self.assertTrue(prop.is_valid((0, 127, 255)))
        self.assertFalse(prop.is_valid((0, -127, 255)))
        self.assertFalse(prop.is_valid((0, 127)))
        self.assertFalse(prop.is_valid((0, 127, 1.0)))
        self.assertFalse(prop.is_valid((0, 127, 255, 255)))
        self.assertTrue(prop.is_valid((0, 127, 255, 1.0)))

        self.assertTrue(prop.is_valid("#00aaff"))
        self.assertTrue(prop.is_valid("#00AAFF"))
        self.assertTrue(prop.is_valid("#00AaFf"))
        self.assertFalse(prop.is_valid("00aaff"))
        self.assertFalse(prop.is_valid("00AAFF"))
        self.assertFalse(prop.is_valid("00AaFf"))
        self.assertFalse(prop.is_valid("#00AaFg"))
        self.assertFalse(prop.is_valid("#00AaFff"))

        self.assertTrue(prop.is_valid("blue"))
        self.assertTrue(prop.is_valid("BLUE"))
        self.assertFalse(prop.is_valid("foobar"))
Example #5
0
class GMapPlot(PlotObject):

    center_lat = Float
    center_lng = Float
    zoom_level = Int(12)

    data_sources = List
    title = String("Bokeh Plot")

    png = String('')
    title = String('')

    # A list of all renderers on this plot; this includes guides as well
    # as glyph renderers
    renderers = List(has_ref=True)
    tools = List(has_ref=True)

    # TODO: These don't appear in the CS source, but are created by mpl.py, so
    # I'm leaving them here for initial compatibility testing.
    axes = List(has_ref=True)
    x_range = Instance(Range1d, has_ref=True)
    y_range = Instance(Range1d, has_ref=True)

    # TODO: How do we want to handle syncing of the different layers?
    # image = List
    # underlay = List
    # glyph = List
    #
    # annotation = List

    height = Int(800)
    width = Int(800)

    border_fill = Color("white")
    canvas_width = Int(800)
    canvas_height = Int(800)
    outer_width = Int(800)
    outer_height = Int(800)
    min_border_top = Int(50)
    min_border_bottom = Int(50)
    min_border_left = Int(50)
    min_border_right = Int(50)
    min_border = Int(50)

    def vm_serialize(self):
        # GlyphRenderers need to serialize their state a little differently,
        # because the internal glyph instance is turned into a glyphspec
        data = super(GMapPlot, self).vm_serialize()
        data.pop('center_lat', None)
        data.pop('center_lng', None)
        data.pop('zoom_level', None)
        data["map_options"] = {
            'lat': self.center_lat,
            'lng': self.center_lng,
            'zoom': self.zoom_level
        }
        self._session.raw_js_snippets(self)
        return data

    @classmethod
    def load_json(cls, attrs, instance=None):
        """Loads all json into a instance of cls, EXCEPT any references
        which are handled in finalize
        """
        inst = super(GMapPlot, cls).load_json(attrs, instance=instance)
        if hasattr(inst, 'map_options'):
            mo = inst.map_options
            del inst.map_options
            inst.center_lat = mo['lat']
            inst.center_lng = mo['lng']
            inst.zoom_level = mo['zoom']
        return inst

    def get_raw_js(self):
        return '<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>'

    def script_inject(self):
        return script_inject(self._session, self._id, self.__view_model__)

    def script_inject_escaped(self):
        return script_inject(self._session, self._id, self.__view_model__)

    def vm_props(self, *args, **kw):
        # FIXME: We need to duplicate the height and width into canvas and
        # outer height/width.  This is a quick fix for the gorpiness, but this
        # needs to be fixed more structurally on the JS side, and then this
        # should be revisited on the Python side.
        if "canvas_width" not in self._changed_vars:
            self.canvas_width = self.width
        if "outer_width" not in self._changed_vars:
            self.outer_width = self.width
        if "canvas_height" not in self._changed_vars:
            self.canvas_height = self.height
        if "outer_height" not in self._changed_vars:
            self.outer_height = self.height
        return super(GMapPlot, self).vm_props(*args, **kw)
Example #6
0
class Plot(PlotObject):

    data_sources = List
    title = String("Bokeh Plot")

    x_range = Instance(DataRange1d, has_ref=True)
    y_range = Instance(DataRange1d, has_ref=True)
    png = String('')
    title = String('')
    # We shouldn't need to create mappers manually on the Python side
    #xmapper = Instance(LinearMapper)
    #ymapper = Instance(LinearMapper)
    #mapper = Instance(GridMapper)

    # A list of all renderers on this plot; this includes guides as well
    # as glyph renderers
    renderers = List(has_ref=True)
    tools = List(has_ref=True)

    # TODO: These don't appear in the CS source, but are created by mpl.py, so
    # I'm leaving them here for initial compatibility testing.
    axes = List(has_ref=True)

    # TODO: How do we want to handle syncing of the different layers?
    # image = List
    # underlay = List
    # glyph = List
    #
    # annotation = List

    height = Int(600)
    width = Int(600)

    background_fill = Color("white")
    border_fill = Color("white")
    canvas_width = Int(400)
    canvas_height = Int(400)
    outer_width = Int(400)
    outer_height = Int(400)
    min_border_top = Int(50)
    min_border_bottom = Int(50)
    min_border_left = Int(50)
    min_border_right = Int(50)
    min_border = Int(50)

    def script_inject(self):
        return script_inject(self._session, self._id, self.__view_model__)

    def script_inject_escaped(self):
        return script_inject(self._session, self._id, self.__view_model__)

    def vm_props(self, *args, **kw):
        # FIXME: We need to duplicate the height and width into canvas and
        # outer height/width.  This is a quick fix for the gorpiness, but this
        # needs to be fixed more structurally on the JS side, and then this
        # should be revisited on the Python side.
        if "canvas_width" not in self._changed_vars:
            self.canvas_width = self.width
        if "outer_width" not in self._changed_vars:
            self.outer_width = self.width
        if "canvas_height" not in self._changed_vars:
            self.canvas_height = self.height
        if "outer_height" not in self._changed_vars:
            self.outer_height = self.height
        return super(Plot, self).vm_props(*args, **kw)
Example #7
0
class CompositeGlyph(HasProps):
    """Represents a subset of data.

    A collection of hetero or homogeneous glyph
    renderers which represent a subset of data. The
    purpose of the composite glyph is to abstract
    away the details of constructing glyphs, based on
    the details of a subset of data, from the grouping
    operations that a generalized builder must implement.

    In general, the Builder operates at the full column
    oriented data source level, segmenting and assigning
    attributes from a large selection, while the composite glyphs
    will typically be passed an array-like structures with
    one or more singlular attributes to apply.

    Another way to explain the concept is that the Builder
    operates as the groupby, as in pandas, while the
    CompositeGlyph operates as the apply.

    What is the responsibility of the Composite Glyph?
        - Produce GlyphRenderers
        - Apply any aggregations
        - Tag the GlyphRenderers with the group label
        - Apply transforms due to chart operations
            - Operations require implementation of special methods
    """

    label = String('All', help='Identifies the subset of data.')
    values = Either(Column(Float), Column(String), help='Array-like values.')
    color = Color(default='gray')
    fill_alpha = Float(default=0.8)

    source = Instance(ColumnDataSource)
    operations = List(Any)
    renderers = List(Instance(GlyphRenderer))

    left_buffer = Float(default=0.0)
    right_buffer = Float(default=0.0)
    top_buffer = Float(default=0.0)
    bottom_buffer = Float(default=0.0)

    def __init__(self, **kwargs):
        label = kwargs.pop('label', None)

        if label is not None:
            if not isinstance(label, str):
                label = str(label)
            kwargs['label'] = label

        super(CompositeGlyph, self).__init__(**kwargs)
        self.setup()

    def setup(self):
        self.renderers = [renderer for renderer in self.build_renderers()]
        if self.renderers is not None:
            self.refresh()

    def refresh(self):
        if self.renderers is not None:
            self.source = self.build_source()
            self._set_sources()

    def build_renderers(self):
        raise NotImplementedError('You must return list of renderers.')

    def build_source(self):
        raise NotImplementedError('You must return ColumnDataSource.')

    def _set_sources(self):
        """Store reference to source in each glyph renderer."""
        for renderer in self.renderers:
            renderer.data_source = self.source

    def __stack__(self, glyphs):
        pass

    def __jitter__(self, glyphs):
        pass

    def __dodge__(self, glyphs):
        pass

    def __overlay__(self, glyphs):
        pass

    def apply_operations(self):
        pass
Example #8
0
class CompositeGlyph(HasProps):
    """Represents a subset of data.

    A collection of hetero or homogeneous glyph
    renderers which represent a subset of data. The
    purpose of the composite glyph is to abstract
    away the details of constructing glyphs, based on
    the details of a subset of data, from the grouping
    operations that a generalized builders must implement.

    In general, the Builder operates at the full column
    oriented data source level, segmenting and assigning
    attributes from a large selection, while the composite glyphs
    will typically be passed an array-like structures with
    one or more singlular attributes to apply.

    Another way to explain the concept is that the Builder
    operates as the groupby, as in pandas, while the
    CompositeGlyph operates as the function used in the apply.

    What is the responsibility of the Composite Glyph?
        - Produce GlyphRenderers
        - Apply any aggregations
        - Tag the GlyphRenderers with the group label
        - Apply transforms due to chart operations
            - Note: Operations require implementation of special methods
    """

    # composite glyph inputs
    label = String('None', help='Identifies the subset of data.')
    values = Either(Column(Float),
                    Column(String),
                    help="""Array-like values,
        which are used as the input to the composite glyph.""")

    # derived from inputs
    source = Instance(ColumnDataSource,
                      help="""The data source used for the contained
        glyph renderers. Simple glyphs part of the composite glyph might not use the
        column data source.""")
    renderers = List(Instance(GlyphRenderer))

    operations = List(Any,
                      help="""A list of chart operations that can be applied to
        manipulate their visual depiction.""")

    color = Color(default='gray',
                  help="""A high level color. Some glyphs will
        implement more specific color attributes for parts or specific glyphs."""
                  )
    line_color = Color(default='black',
                       help="""A default outline color for contained
        glyphs.""")
    fill_alpha = Float(default=0.8)

    left_buffer = Float(default=0.0)
    right_buffer = Float(default=0.0)
    top_buffer = Float(default=0.0)
    bottom_buffer = Float(default=0.0)

    def __init__(self, **kwargs):
        label = kwargs.pop('label', None)

        if label is not None:
            if not isinstance(label, str):
                label = str(label)
            kwargs['label'] = label

        super(CompositeGlyph, self).__init__(**kwargs)

    def setup(self):
        """Build renderers and data source and set sources on renderers."""
        self.renderers = [renderer for renderer in self.build_renderers()]
        if self.renderers is not None:
            self.refresh()

    def refresh(self):
        """Update the GlyphRenderers.

        .. note:
            this method would be called after data is added.
        """
        if self.renderers is not None:
            self.source = self.build_source()
            self._set_sources()

    def build_renderers(self):
        raise NotImplementedError('You must return list of renderers.')

    def build_source(self):
        raise NotImplementedError('You must return ColumnDataSource.')

    def _set_sources(self):
        """Store reference to source in each GlyphRenderer.

        .. note::
            if the glyphs that are part of the composite glyph differ, you may have to
            override this method and handle the sources manually.
        """
        for renderer in self.renderers:
            renderer.data_source = self.source

    def __stack__(self, glyphs):
        """A special method the `stack` function applies to composite glyphs."""
        pass

    def __jitter__(self, glyphs):
        """A special method the `jitter` function applies to composite glyphs."""
        pass

    def __dodge__(self, glyphs):
        """A special method the `dodge` function applies to composite glyphs."""
        pass

    def __overlay__(self, glyphs):
        """A special method the `overlay` function applies to composite glyphs."""
        pass

    def apply_operations(self):
        pass