Пример #1
0
 def test_bounds_all_nans(self):
     myarray = empty(10)
     myarray[:] = nan
     sd = ArrayDataSource(myarray)
     bounds = sd.get_bounds()
     self.assertTrue(isnan(bounds[0]))
     self.assertTrue(isnan(bounds[1]))
Пример #2
0
		def __init__(self,data_q,num):
			super(PlotterWindow,self).__init__()

			self.data_q = data_q

			self.x = ArrayDataSource(zeros(num))
			self.y = ArrayDataSource(zeros(num))
			self.v = MultiArrayDataSource(zeros((num,2)))

			xrange = DataRange1D()
			xrange.add(self.x)
			yrange = DataRange1D()
			yrange.add(self.y)

			quiverplot = QuiverPlot(index=self.x,value=self.y,vectors=self.v,
				index_mapper=LinearMapper(range=xrange),
				value_mapper=LinearMapper(range=yrange),
				bgcolor='white')
			add_default_axes(quiverplot)
			add_default_grids(quiverplot)

			quiverplot.tools.append(PanTool(quiverplot,constrain_key='shift'))
			quiverplot.overlays.append(ZoomTool(quiverplot))

			self.plot = OverlayPlotContainer(quiverplot, padding=50)
			self.timer = Timer(50.0, self.onTimer)

			self.configure_traits()
Пример #3
0
 def test_init_defaults(self):
     data_source = ArrayDataSource()
     assert_array_equal(data_source._data, [])
     self.assertEqual(data_source.value_dimension, "scalar")
     self.assertEqual(data_source.index_dimension, "scalar")
     self.assertEqual(data_source.sort_order, "none")
     self.assertFalse(data_source.is_masked())
     self.assertEqual(data_source.persist_data, True)
Пример #4
0
 def recalculate(self):
     if self.data_range is not None:
         low, high = self.data_range.low, self.data_range.high
         x = _xfunc(low, high)
         new_array = p_yes(self.a, self.m, self.k, x)
         ArrayDataSource.set_data(self, new_array)
     else:
         self._data = np.array([], dtype='f')
Пример #5
0
    def test_simple_map(self):

        a = ArrayDataSource(array([0.0, 0.5, 1.0]))
        self.colormap.range.add(a)
        b = self.colormap.map_screen(a.get_data())
        self.colormap.range.remove(a)

        expected = array([0.0, 0.5, 1.0])

        close = allclose(ravel(b[:,:1]), expected, atol=0.02)
        self.assertTrue(close,
            "Simple map failed.  Expected %s.  Got %s" % (expected, b[:,:1]))

        return
Пример #6
0
    def test_bounds(self):
        # ascending
        bounds = self.data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order="descending")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # no order
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order="none")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 18))
    def test_reverse_construction(self):
        mapper = LinearMapper()
        r = DataRange1D()
        ds = ArrayDataSource()
        ary = array([1,2,3,4,5,6,7])

        mapper.range = r
        mapper.low_pos = 1.0
        mapper.high_pos = 7.0
        r.add(ds)
        ds.set_data(ary)

        self.assertTrue(r.low == 1)
        self.assertTrue(r.high == 7)
        screen_pts = mapper.map_screen(array([1,3,7]))
        self.assertTrue(tuple(screen_pts) == (1.0, 3.0, 7.0))
        return
Пример #8
0
    def test_piecewise_construction(self):
        ary = array([1,2,3,4,5,6,7])
        ds = ArrayDataSource()
        ds.set_data(ary)
        r = DataRange1D()
        r.add(ds)
        self.assert_(r.low_setting == "auto")
        self.assert_(r.high_setting == "auto")
        self.assert_(r.low == 1)
        self.assert_(r.high == 7)

        mapper = LinearMapper()
        mapper.range = r
        mapper.low_pos = 1.0
        mapper.high_pos = 7.0
        screen_pts = mapper.map_screen(array([1,3,7]))
        self.assert_(tuple(screen_pts) == (1.0, 3.0, 7.0))
        return
Пример #9
0
    def test_array_factory(self):
        """ Test that the array factory creates valid colormap. """

        colors = array([[0.0,0.0,0.0], [1.0,1.0,1.0]])
        cm = ColorMapper.from_palette_array(colors)
        cm.range = DataRange1D()

        ar = ArrayDataSource(array([0.0, 0.5, 1.0]))
        cm.range.add(ar)
        b = cm.map_screen(ar.get_data())
        cm.range.remove(ar)

        expected = array([0.0, 0.5, 1.0])

        self.assertTrue(allclose(ravel(b[:,:1]), expected, atol=0.02),
            "Array factory failed.  Expected %s.  Got %s" % (expected, b[:,:1]))

        return
Пример #10
0
	class PlotterWindow(HasTraits):
		plot = Instance(OverlayPlotContainer)
		timer = Instance(Timer)

		traits_view = View(
			Item('plot',editor=ComponentEditor(),show_label=False),
			width=500,height=500,resizable=True,title="Plotter")

		def __init__(self,data_q,num):
			super(PlotterWindow,self).__init__()

			self.data_q = data_q

			self.x = ArrayDataSource(zeros(num))
			self.y = ArrayDataSource(zeros(num))
			self.v = MultiArrayDataSource(zeros((num,2)))

			xrange = DataRange1D()
			xrange.add(self.x)
			yrange = DataRange1D()
			yrange.add(self.y)

			quiverplot = QuiverPlot(index=self.x,value=self.y,vectors=self.v,
				index_mapper=LinearMapper(range=xrange),
				value_mapper=LinearMapper(range=yrange),
				bgcolor='white')
			add_default_axes(quiverplot)
			add_default_grids(quiverplot)

			quiverplot.tools.append(PanTool(quiverplot,constrain_key='shift'))
			quiverplot.overlays.append(ZoomTool(quiverplot))

			self.plot = OverlayPlotContainer(quiverplot, padding=50)
			self.timer = Timer(50.0, self.onTimer)

			self.configure_traits()

		def onTimer(self,*args):
			d = self.data_q.get()

			self.x.set_data(d[0])
			self.y.set_data(d[1])
			self.v.set_data(d[2])
Пример #11
0
    def test_reverse_map(self):
        # sort_order ascending
        myarray = arange(10)
        data_source = ArrayDataSource(myarray, sort_order='ascending')

        self.assertEqual(data_source.reverse_map(4.0), 4)

        # sort_order descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order='descending')

        self.assertEqual(data_source.reverse_map(4.0), 5)

        # sort_order none
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order='none')

        with self.assertRaises(NotImplementedError):
            data_source.reverse_map(3)
Пример #12
0
    def test_bounds(self):
        # ascending
        myarray = arange(10)
        sd = ArrayDataSource(myarray, sort_order="ascending")
        bounds = sd.get_bounds()
        self.assert_(bounds == (0,9))

        # descending
        myarray = arange(10)[::-1]
        sd = ArrayDataSource(myarray, sort_order="descending")
        bounds = sd.get_bounds()
        self.assert_(bounds == (0,9))

        # no order
        myarray = array([12,3,0,9,2,18,3])
        sd = ArrayDataSource(myarray, sort_order="none")
        bounds = sd.get_bounds()
        self.assert_(bounds == (0,18))
        return
Пример #13
0
    def test_change_min_max(self):
        """ Test that changing min_value and max_value does not break map. """

        datarange = self.colormap.range

        # Perform a dummy mapping.
        a = ArrayDataSource(array([0.0, 0.5, 1.0]))
        datarange.add(a)
        b = self.colormap.map_screen(a.get_data())
        datarange.remove(a)

        # Update the min_value.
        datarange.low = -1.0

        # Test that the map still works.
        a = ArrayDataSource(array([-1.0, 0.0, 1.0]))
        datarange.add(a)
        b = self.colormap.map_screen(a.get_data())
        datarange.remove(a)
        expected = array([0.0, 0.5, 1.0])

        close = allclose(ravel(b[:,:1]), expected, atol=0.02)
        self.assertTrue(close,
            "Changing min value broke map.  Expected %s.  Got %s" % (expected, b[:,:1]))

        # Update the max_value.
        datarange.high = 0.0
        # Test that the map still works.
        a = ArrayDataSource(array([-1.0, -0.5, 0.0]))
        datarange.add(a)
        b = self.colormap.map_screen(a.get_data())
        datarange.remove(a)
        expected = array([0.0, 0.5, 1.0])

        close = allclose(ravel(b[:,:1]), expected, atol=0.02)
        self.assertTrue(close,
            "Changing min value broke map.  Expected %s.  Got %s" % (expected, b[:,:1]))


        return
Пример #14
0
def _create_plot_component():

    # Create the data and datasource objects
    numpoints = 500
    index = arange(numpoints)
    returns = random.lognormal(0.01, 0.1, size=numpoints)
    price = 100.0 * cumprod(returns)
    volume = abs(random.normal(1000.0, 1500.0, size=numpoints) + 2000.0)

    time_ds = ArrayDataSource(index)
    vol_ds = ArrayDataSource(volume, sort_order="none")
    price_ds = ArrayDataSource(price, sort_order="none")

    xmapper = LinearMapper(range=DataRange1D(time_ds))
    vol_mapper = LinearMapper(range=DataRange1D(vol_ds))
    price_mapper = LinearMapper(range=DataRange1D(price_ds))

    price_plot = FilledLinePlot(index=time_ds,
                                value=price_ds,
                                index_mapper=xmapper,
                                value_mapper=price_mapper,
                                edge_color="blue",
                                face_color="paleturquoise",
                                alpha=0.5,
                                bgcolor="white",
                                border_visible=True)
    add_default_grids(price_plot)
    price_plot.overlays.append(PlotAxis(price_plot, orientation='left'))
    price_plot.overlays.append(PlotAxis(price_plot, orientation='bottom'))
    price_plot.tools.append(
        PanTool(price_plot, constrain=True, constrain_direction="x"))
    price_plot.overlays.append(
        ZoomTool(
            price_plot,
            drag_button="right",
            always_on=True,
            tool_mode="range",
            axis="index",
            color='red',
        ))

    vol_plot = BarPlot(index=time_ds,
                       value=vol_ds,
                       index_mapper=xmapper,
                       value_mapper=vol_mapper,
                       line_color="transparent",
                       fill_color="black",
                       bar_width=1.0,
                       bar_width_type="screen",
                       antialias=False,
                       height=400,
                       resizable="h",
                       bgcolor="white",
                       border_visible=True)

    add_default_grids(vol_plot)
    vol_plot.underlays.append(PlotAxis(vol_plot, orientation='left'))
    vol_plot.tools.append(
        PanTool(vol_plot, constrain=True, constrain_direction="x"))

    container = VPlotContainer(bgcolor="lightblue",
                               spacing=20,
                               padding=50,
                               fill_padding=False)
    container.add(vol_plot)
    container.add(price_plot)
    container.overlays.append(
        PlotLabel(
            "Financial Plot",
            component=container,
            #font="Times New Roman 24"))
            font="Arial 24"))
    return container
Пример #15
0
 def test_bounds_non_numeric(self):
     myarray = np.array([u'abc', u'foo', u'bar', u'def'], dtype=unicode)
     data_source = ArrayDataSource(myarray)
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (u'abc', u'def'))
Пример #16
0
 def test_bounds_negative_positive_inf(self):
     data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (-np.inf, np.inf))
Пример #17
0
class ArrayDataSourceTestCase(UnittestTools, unittest.TestCase):

    def setUp(self):
        self.myarray = arange(10)
        self.mymask = array([i % 2 for i in self.myarray], dtype=bool)
        self.data_source = ArrayDataSource(self.myarray)

    def test_init_defaults(self):
        data_source = ArrayDataSource()
        assert_array_equal(data_source._data, [])
        self.assertEqual(data_source.value_dimension, "scalar")
        self.assertEqual(data_source.index_dimension, "scalar")
        self.assertEqual(data_source.sort_order, "none")
        self.assertFalse(data_source.is_masked())
        self.assertEqual(data_source.persist_data, True)

    def test_basic_setup(self):
        assert_array_equal(self.myarray, self.data_source._data)
        self.assertEqual(self.data_source.value_dimension, "scalar")
        self.assertEqual(self.data_source.sort_order, "none")
        self.assertFalse(self.data_source.is_masked())

    def test_set_data(self):
        new_array = arange(0, 20, 2)

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_data(new_array)

        assert_array_equal(new_array, self.data_source._data)
        self.assertEqual(self.data_source.get_bounds(), (0, 18))
        self.assertEqual(self.data_source.sort_order, "none")

    def test_set_data_ordered(self):
        new_array = arange(20, 0, -2)

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_data(new_array, sort_order='descending')

        assert_array_equal(new_array, self.data_source._data)
        self.assertEqual(self.data_source.get_bounds(), (2, 20))
        self.assertEqual(self.data_source.sort_order, "descending")

    def test_set_mask(self):
        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_mask(self.mymask)

        assert_array_equal(self.myarray, self.data_source._data)
        assert_array_equal(self.mymask, self.data_source._cached_mask)
        self.assertTrue(self.data_source.is_masked())
        self.assertEqual(self.data_source.get_bounds(), (0, 9))

    def test_remove_mask(self):
        self.data_source.set_mask(self.mymask)
        self.assertTrue(self.data_source.is_masked())

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.remove_mask()

        assert_array_equal(self.myarray, self.data_source._data)
        self.assertIsNone(self.data_source._cached_mask, None)
        self.assertFalse(self.data_source.is_masked())
        self.assertEqual(self.data_source.get_bounds(), (0, 9))

    def test_get_data(self):
        assert_array_equal(self.myarray, self.data_source.get_data())

    def test_get_data_no_data(self):
        data_source = ArrayDataSource(None)

        assert_array_equal(data_source.get_data(), 0.0)

    def test_get_data_mask(self):
        self.data_source.set_mask(self.mymask)

        data, mask = self.data_source.get_data_mask()
        assert_array_equal(data, self.myarray)
        assert_array_equal(mask, self.mymask)

    @unittest.skip('get_data_mask() fails in this case')
    def test_get_data_mask_no_data(self):
        data_source = ArrayDataSource(None)

        data, mask = data_source.get_data_mask()
        assert_array_equal(data, 0.0)
        assert_array_equal(mask, True)

    def test_get_data_mask_no_mask(self):
        data, mask = self.data_source.get_data_mask()
        assert_array_equal(data, self.myarray)
        assert_array_equal(mask, ones(shape=10, dtype=bool))

    def test_bounds(self):
        # ascending
        bounds = self.data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order="descending")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # no order
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order="none")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 18))

    def test_bounds_length_one(self):
        # this is special-cased in the code, so exercise the code path
        data_source = ArrayDataSource(array([1.0]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (1.0, 1.0))

    def test_bounds_length_zero(self):
        # this is special-cased in the code, so exercise the code path
        data_source = ArrayDataSource(array([]))
        bounds = data_source.get_bounds()
        # XXX this is sort of inconsistent with test_bounds_all_nans()
        self.assertEqual(bounds, (0, 0))

    def test_bounds_empty(self):
        data_source = ArrayDataSource()
        bounds = data_source.get_bounds()
        # XXX this is sort of inconsistent with test_bounds_all_nans()
        self.assertEqual(bounds, (0, 0))

    def test_bounds_all_nans(self):
        myarray = empty(10)
        myarray[:] = nan
        sd = ArrayDataSource(myarray)
        bounds = sd.get_bounds()
        self.assertTrue(isnan(bounds[0]))
        self.assertTrue(isnan(bounds[1]))

    def test_bounds_some_nan(self):
        data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 18))

    def test_bounds_negative_inf(self):
        data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, 18, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (-np.inf, 18))

    def test_bounds_positive_inf(self):
        data_source = ArrayDataSource(array([12, 3, 0, 9, 2, np.inf, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, np.inf))

    def test_bounds_negative_positive_inf(self):
        data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (-np.inf, np.inf))

    def test_bounds_non_numeric(self):
        myarray = np.array([u'abc', u'foo', u'bar', u'def'], dtype=unicode)
        data_source = ArrayDataSource(myarray)
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (u'abc', u'def'))

    def test_data_size(self):
        # We know that ArrayDataTestCase always returns the exact length of
        # its data
        myarray = arange(913)
        data_source = ArrayDataSource(myarray)
        self.assertEqual(len(myarray), data_source.get_size())

    def test_reverse_map(self):
        # sort_order ascending
        myarray = arange(10)
        data_source = ArrayDataSource(myarray, sort_order='ascending')

        self.assertEqual(data_source.reverse_map(4.0), 4)

        # sort_order descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order='descending')

        self.assertEqual(data_source.reverse_map(4.0), 5)

        # sort_order none
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order='none')

        with self.assertRaises(NotImplementedError):
            data_source.reverse_map(3)

    def test_metadata(self):
        self.assertEqual(self.data_source.metadata,
                         {'annotations': [], 'selections': []})

    def test_metadata_changed(self):
        with self.assertTraitChanges(self.data_source, 'metadata_changed',
                                     count=1):
            self.data_source.metadata = {'new_metadata': True}

    def test_metadata_items_changed(self):
        with self.assertTraitChanges(self.data_source, 'metadata_changed',
                                     count=1):
            self.data_source.metadata['new_metadata'] = True

    def test_serialization_state(self):
        state = self.data_source.__getstate__()
        self.assertNotIn('value_dimension', state)
        self.assertNotIn('index_dimension', state)
        self.assertNotIn('persist_data', state)

    @unittest.skip("persist_data probably shouldn't be persisted")
    def test_serialization_state_no_persist(self):
        self.data_source.persist_data = False

        state = self.data_source.__getstate__()
        self.assertNotIn('value_dimension', state)
        self.assertNotIn('index_dimension', state)
        self.assertNotIn('persist_data', state)
        for key in ["_data", "_cached_mask", "_cached_bounds", "_min_index",
                    "_max_index"]:
            self.assertIn(key, state)

    @unittest.skip("I think this is just broken")
    def test_serialization_post_load(self):
        self.data_source.set_mask(self.mymask)

        pickled_data_source = pickle.dumps(self.data_source)
        unpickled_data_source = pickle.loads(pickled_data_source)
        unpickled_data_source._post_load()

        self.assertEqual(unpickled_data_source._cached_bounds, ())
        self.assertEqual(unpickled_data_source._cached_mask, None)

        assert_array_equal(self.data_source.get_data(),
                           unpickled_data_source.get_data())

        mask = unpickled_data_source.get_data_mask()[1]
        assert_array_equal(mask, ones(10))
Пример #18
0
 def test_bounds_empty(self):
     data_source = ArrayDataSource()
     bounds = data_source.get_bounds()
     # XXX this is sort of inconsistent with test_bounds_all_nans()
     self.assertEqual(bounds, (0, 0))
Пример #19
0
 def test_bounds_length_one(self):
     # this is special-cased in the code, so exercise the code path
     data_source = ArrayDataSource(array([1.0]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (1.0, 1.0))
Пример #20
0
 def test_bounds_length_one(self):
     # this is special-cased in the code, so exercise the code path
     data_source = ArrayDataSource(array([1.0]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (1.0, 1.0))
Пример #21
0
    def new_series(self, x=None, y=None, plotid=0, **kw):
        """
        """

        plot, scatter, _line = super(ResidualsGraph,
                                     self).new_series(x=x,
                                                      y=y,
                                                      plotid=plotid,
                                                      **kw)
        for underlay in plot.underlays:
            if underlay.orientation == 'bottom':
                underlay.visible = False
                underlay.padding_bottom = 0
        plot.padding_bottom = 0

        x, y, res = self.calc_residuals(plotid=plotid)

        ressplit = self._split_residual(x, res)
        resneg = ArrayDataSource(ressplit[1])
        xneg = ArrayDataSource(ressplit[0])
        respos = ArrayDataSource(ressplit[3])
        xpos = ArrayDataSource(ressplit[2])

        yrange = DataRange1D(ArrayDataSource(res))

        ymapper = LinearMapper(range=yrange)

        container = container_factory(type='o',
                                      padding=[50, 15, 0, 30],
                                      height=75,
                                      resizable='h')
        bar = BarPlot(index=xneg,
                      value=resneg,
                      index_mapper=scatter.index_mapper,
                      value_mapper=ymapper,
                      bar_width=0.2,
                      line_color='blue',
                      fill_color='blue',
                      border_visible=True)

        #        left_axis = PlotAxis(bar, orientation = 'left')
        # bottom_axis=PlotAxis(bar,orientation='bottom')

        kw = dict(vtitle='residuals')
        if self.xtitle:
            kw['htitle'] = self.xtitle
        add_default_axes(bar, **kw)
        hgrid = PlotGrid(mapper=ymapper,
                         component=bar,
                         orientation='horizontal',
                         line_color='lightgray',
                         line_style='dot')

        bar.underlays.append(hgrid)
        #        bar.underlays.append(left_axis)
        #        bar.underlays.append(bottom_axis)

        bar2 = BarPlot(
            index=xpos,
            value=respos,
            index_mapper=scatter.index_mapper,
            value_mapper=ymapper,
            bar_width=0.2,
            line_color='green',
            fill_color='green',
            # bgcolor = 'green',
            resizable='hv',
            border_visible=True,
            # padding = [30, 5, 0, 30]
        )
        bar2.overlays.append(GuideOverlay(bar2, value=0, color=(0, 0, 0)))
        bar2.underlays.append(hgrid)
        container.add(bar)
        container.add(bar2)

        # container.add(PlotLabel('foo'))

        self.residual_plots = [bar, bar2]
        self.plotcontainer.add(container)
Пример #22
0
    def test_get_data_no_data(self):
        data_source = ArrayDataSource(None)

        assert_array_equal(data_source.get_data(), 0.0)
Пример #23
0
 def setUp(self):
     self.myarray = arange(10)
     self.mymask = array([i % 2 for i in self.myarray], dtype=bool)
     self.data_source = ArrayDataSource(self.myarray)
Пример #24
0
class ArrayDataSourceTestCase(UnittestTools, unittest.TestCase):
    def setUp(self):
        self.myarray = arange(10)
        self.mymask = array([i % 2 for i in self.myarray], dtype=bool)
        self.data_source = ArrayDataSource(self.myarray)

    def test_init_defaults(self):
        data_source = ArrayDataSource()
        assert_array_equal(data_source._data, [])
        self.assertEqual(data_source.value_dimension, "scalar")
        self.assertEqual(data_source.index_dimension, "scalar")
        self.assertEqual(data_source.sort_order, "none")
        self.assertFalse(data_source.is_masked())
        self.assertEqual(data_source.persist_data, True)

    def test_basic_setup(self):
        assert_array_equal(self.myarray, self.data_source._data)
        self.assertEqual(self.data_source.value_dimension, "scalar")
        self.assertEqual(self.data_source.sort_order, "none")
        self.assertFalse(self.data_source.is_masked())

    def test_set_data(self):
        new_array = arange(0, 20, 2)

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_data(new_array)

        assert_array_equal(new_array, self.data_source._data)
        self.assertEqual(self.data_source.get_bounds(), (0, 18))
        self.assertEqual(self.data_source.sort_order, "none")

    def test_set_data_ordered(self):
        new_array = arange(20, 0, -2)

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_data(new_array, sort_order='descending')

        assert_array_equal(new_array, self.data_source._data)
        self.assertEqual(self.data_source.get_bounds(), (2, 20))
        self.assertEqual(self.data_source.sort_order, "descending")

    def test_set_mask(self):
        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.set_mask(self.mymask)

        assert_array_equal(self.myarray, self.data_source._data)
        assert_array_equal(self.mymask, self.data_source._cached_mask)
        self.assertTrue(self.data_source.is_masked())
        self.assertEqual(self.data_source.get_bounds(), (0, 9))

    def test_remove_mask(self):
        self.data_source.set_mask(self.mymask)
        self.assertTrue(self.data_source.is_masked())

        with self.assertTraitChanges(self.data_source, 'data_changed',
                                     count=1):
            self.data_source.remove_mask()

        assert_array_equal(self.myarray, self.data_source._data)
        self.assertIsNone(self.data_source._cached_mask, None)
        self.assertFalse(self.data_source.is_masked())
        self.assertEqual(self.data_source.get_bounds(), (0, 9))

    def test_get_data(self):
        assert_array_equal(self.myarray, self.data_source.get_data())

    def test_get_data_no_data(self):
        data_source = ArrayDataSource(None)

        assert_array_equal(data_source.get_data(), 0.0)

    def test_get_data_mask(self):
        self.data_source.set_mask(self.mymask)

        data, mask = self.data_source.get_data_mask()
        assert_array_equal(data, self.myarray)
        assert_array_equal(mask, self.mymask)

    @unittest.skip('get_data_mask() fails in this case')
    def test_get_data_mask_no_data(self):
        data_source = ArrayDataSource(None)

        data, mask = data_source.get_data_mask()
        assert_array_equal(data, 0.0)
        assert_array_equal(mask, True)

    def test_get_data_mask_no_mask(self):
        data, mask = self.data_source.get_data_mask()
        assert_array_equal(data, self.myarray)
        assert_array_equal(mask, ones(shape=10, dtype=bool))

    def test_bounds(self):
        # ascending
        bounds = self.data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order="descending")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 9))

        # no order
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order="none")
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 18))

    def test_bounds_length_one(self):
        # this is special-cased in the code, so exercise the code path
        data_source = ArrayDataSource(array([1.0]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (1.0, 1.0))

    def test_bounds_length_zero(self):
        # this is special-cased in the code, so exercise the code path
        data_source = ArrayDataSource(array([]))
        bounds = data_source.get_bounds()
        # XXX this is sort of inconsistent with test_bounds_all_nans()
        self.assertEqual(bounds, (0, 0))

    def test_bounds_empty(self):
        data_source = ArrayDataSource()
        bounds = data_source.get_bounds()
        # XXX this is sort of inconsistent with test_bounds_all_nans()
        self.assertEqual(bounds, (0, 0))

    def test_bounds_all_nans(self):
        myarray = empty(10)
        myarray[:] = nan
        sd = ArrayDataSource(myarray)
        bounds = sd.get_bounds()
        self.assertTrue(isnan(bounds[0]))
        self.assertTrue(isnan(bounds[1]))

    def test_bounds_some_nan(self):
        data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, 18))

    def test_bounds_negative_inf(self):
        data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, 18, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (-np.inf, 18))

    def test_bounds_positive_inf(self):
        data_source = ArrayDataSource(array([12, 3, 0, 9, 2, np.inf, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (0, np.inf))

    def test_bounds_negative_positive_inf(self):
        data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3]))
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (-np.inf, np.inf))

    def test_bounds_non_numeric(self):
        myarray = np.array([u'abc', u'foo', u'bar', u'def'],
                           dtype=six.text_type)
        data_source = ArrayDataSource(myarray)
        bounds = data_source.get_bounds()
        self.assertEqual(bounds, (u'abc', u'def'))

    def test_data_size(self):
        # We know that ArrayDataTestCase always returns the exact length of
        # its data
        myarray = arange(913)
        data_source = ArrayDataSource(myarray)
        self.assertEqual(len(myarray), data_source.get_size())

    def test_reverse_map(self):
        # sort_order ascending
        myarray = arange(10)
        data_source = ArrayDataSource(myarray, sort_order='ascending')

        self.assertEqual(data_source.reverse_map(4.0), 4)

        # sort_order descending
        myarray = arange(10)[::-1]
        data_source = ArrayDataSource(myarray, sort_order='descending')

        self.assertEqual(data_source.reverse_map(4.0), 5)

        # sort_order none
        myarray = array([12, 3, 0, 9, 2, 18, 3])
        data_source = ArrayDataSource(myarray, sort_order='none')

        with self.assertRaises(NotImplementedError):
            data_source.reverse_map(3)

    def test_metadata(self):
        self.assertEqual(self.data_source.metadata, {
            'annotations': [],
            'selections': []
        })

    def test_metadata_changed(self):
        with self.assertTraitChanges(self.data_source,
                                     'metadata_changed',
                                     count=1):
            self.data_source.metadata = {'new_metadata': True}

    def test_metadata_items_changed(self):
        with self.assertTraitChanges(self.data_source,
                                     'metadata_changed',
                                     count=1):
            self.data_source.metadata['new_metadata'] = True

    def test_serialization_state(self):
        state = self.data_source.__getstate__()
        self.assertNotIn('value_dimension', state)
        self.assertNotIn('index_dimension', state)
        self.assertNotIn('persist_data', state)

    @unittest.skip("persist_data probably shouldn't be persisted")
    def test_serialization_state_no_persist(self):
        self.data_source.persist_data = False

        state = self.data_source.__getstate__()
        self.assertNotIn('value_dimension', state)
        self.assertNotIn('index_dimension', state)
        self.assertNotIn('persist_data', state)
        for key in [
                "_data", "_cached_mask", "_cached_bounds", "_min_index",
                "_max_index"
        ]:
            self.assertIn(key, state)

    @unittest.skip("I think this is just broken")
    def test_serialization_post_load(self):
        self.data_source.set_mask(self.mymask)

        pickled_data_source = pickle.dumps(self.data_source)
        unpickled_data_source = pickle.loads(pickled_data_source)
        unpickled_data_source._post_load()

        self.assertEqual(unpickled_data_source._cached_bounds, ())
        self.assertEqual(unpickled_data_source._cached_mask, None)

        assert_array_equal(self.data_source.get_data(),
                           unpickled_data_source.get_data())

        mask = unpickled_data_source.get_data_mask()[1]
        assert_array_equal(mask, ones(10))
Пример #25
0
 def test_data_size(self):
     # We know that ArrayDataTestCase always returns the exact length of
     # its data
     myarray = arange(913)
     data_source = ArrayDataSource(myarray)
     self.assertEqual(len(myarray), data_source.get_size())
Пример #26
0
 def test_bounds_non_numeric(self):
     myarray = np.array([u'abc', u'foo', u'bar', u'def'],
                        dtype=six.text_type)
     data_source = ArrayDataSource(myarray)
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (u'abc', u'def'))
Пример #27
0
    def test_get_data_no_data(self):
        data_source = ArrayDataSource(None)

        assert_array_equal(data_source.get_data(), 0.0)
Пример #28
0
 def test_bounds_negative_positive_inf(self):
     data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (-np.inf, np.inf))
Пример #29
0
 def test_bounds_non_numeric(self):
     myarray = np.array([u'abc', u'foo', u'bar', u'def'], dtype=unicode)
     sd = ArrayDataSource(myarray)
     bounds = sd.get_bounds()
     self.assertEqual(bounds, (u'abc', u'def'))
Пример #30
0
    def test_get_data_mask_no_data(self):
        data_source = ArrayDataSource(None)

        data, mask = data_source.get_data_mask()
        assert_array_equal(data, 0.0)
        assert_array_equal(mask, True)
Пример #31
0
 def test_basic_set_get(self):
     myarray = arange(10)
     sd = ArrayDataSource(myarray)
     self.assertTrue(allclose(myarray, sd._data))
     self.assert_(sd.value_dimension == "scalar")
     return
Пример #32
0
 def test_bounds_length_zero(self):
     # this is special-cased in the code, so exercise the code path
     data_source = ArrayDataSource(array([]))
     bounds = data_source.get_bounds()
     # XXX this is sort of inconsistent with test_bounds_all_nans()
     self.assertEqual(bounds, (0, 0))
Пример #33
0
 def test_data_size(self):
     # We know that ScalarData always returns the exact length of its data
     myarray = arange(913)
     sd = ArrayDataSource(myarray)
     self.assert_(len(myarray) == sd.get_size())
     return
def _create_plot_component():
    numpts = 50
    x = random.rand(numpts)
    y = random.rand(numpts)
    cls = random.rand(numpts)
    colors = [1.0 if i > 0.5 else 0.0 for i in cls]
    marker = [1.0 if i > 0.5 else 0.0 for i in cls]
    #plt.figure()
    #plt.scatter(x,y,c=colors)
    #plt.show()

    # Create some data

    #    marker_size = numpy.random.normal(4.0, 4.0, numpts)

    # Create a plot data object and give it this data
    pd = ArrayPlotData()
    pd.set_data("index", x)
    pd.set_data("value", y)

    # Because this is a non-standard renderer, we can't call plot.plot, which
    # sets up the array data sources, mappers and default index/value ranges.
    # So, its gotta be done manually for now.

    index_ds = ArrayDataSource(x)
    value_ds = ArrayDataSource(y)
    color_ds = ArrayDataSource(colors)

    # Create the plot
    plot = Plot(pd)
    plot.index_range.add(index_ds)
    plot.value_range.add(value_ds)

    # Create the index and value mappers using the plot data ranges
    imapper = LinearMapper(range=plot.index_range)
    vmapper = LinearMapper(range=plot.value_range)

    # Create the scatter renderer
    scatter = ColormappedScatterPlot(
        index=index_ds,
        value=value_ds,
        color_data=color_ds,
        color_mapper=jet(range=DataRange1D(low=0.0, high=1.0)),
        fill_alpha=0.4,
        index_mapper=imapper,
        value_mapper=vmapper,
        marker='circle',
        marker_size=4)

    # Append the renderer to the list of the plot's plots
    plot.add(scatter)
    plot.plots['var_size_scatter'] = [scatter]

    # Tweak some of the plot properties
    plot.title = "Colored Scatter Plot"
    plot.line_width = 0.5
    plot.padding = 50

    # Attach some tools to the plot
    plot.tools.append(PanTool(plot, constrain_key="shift"))
    zoom = ZoomTool(component=plot, tool_mode="box", always_on=False)
    plot.overlays.append(zoom)

    return plot
Пример #35
0
def create_gridded_scatter_plot(x,
                                y,
                                orientation="h",
                                color="red",
                                width=1.0,
                                fill_color="red",
                                marker="square",
                                marker_size=2,
                                value_mapper_class=LinearMapper,
                                padding=30):

    assert len(x) == len(y)

    # If you know it is monotonically increasing, sort_order can
    # be set to 'ascending'
    index = ArrayDataSource(x, sort_order='none')
    value = ArrayDataSource(y, sort_order="none")

    index_range = DataRange1D(tight_bounds=False)
    index_range.add(index)
    index_mapper = LinearMapper(range=index_range)

    value_range = DataRange1D(tight_bounds=False)
    value_range.add(value)
    value_mapper = value_mapper_class(range=value_range)

    plot = ScatterPlot(
        index=index,
        value=value,
        index_mapper=index_mapper,
        value_mapper=value_mapper,
        orientation=orientation,
        color=color,
        fill_color=fill_color,
        marker=marker,
        marker_size=marker_size,
        padding=[40, 15, 15, 20],  # left, right, top, bottom
        border_visible=True,
        border_width=1,
        bgcolor="white",
        use_backbuffer=True,
        backbuffer_padding=False,
        unified_draw=True,
        draw_layer="plot",
        overlay_border=True)

    vertical_grid = PlotGrid(component=plot,
                             mapper=index_mapper,
                             orientation='vertical',
                             line_color="gray",
                             line_style='dot',
                             use_draw_order=True)

    horizontal_grid = PlotGrid(component=plot,
                               mapper=value_mapper,
                               orientation='horizontal',
                               line_color="gray",
                               line_style='dot',
                               use_draw_order=True)

    vertical_axis = PlotAxis(orientation='left',
                             mapper=plot.value_mapper,
                             use_draw_order=True)

    horizontal_axis = PlotAxis(orientation='bottom',
                               title='Time (s)',
                               mapper=plot.index_mapper,
                               use_draw_order=True)

    plot.underlays.append(vertical_grid)
    plot.underlays.append(horizontal_grid)

    # Have to add axes to overlays because we are backbuffering the main plot,
    # and only overlays get to render in addition to the backbuffer.
    plot.overlays.append(vertical_axis)
    plot.overlays.append(horizontal_axis)
    return plot
Пример #36
0
 def test_bounds_some_nan(self):
     data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (0, 18))
Пример #37
0
 def test_bounds_empty(self):
     data_source = ArrayDataSource()
     bounds = data_source.get_bounds()
     # XXX this is sort of inconsistent with test_bounds_all_nans()
     self.assertEqual(bounds, (0, 0))
Пример #38
0
 def setUp(self):
     self.myarray = arange(10)
     self.mymask = array([i % 2 for i in self.myarray], dtype=bool)
     self.data_source = ArrayDataSource(self.myarray)
Пример #39
0
    mod_publisher = NumpyPublisher(
        reactive_data_generator, 'mod', frequency=30,
    )

    # Create a data sources
    sin_data_source = DataSource(publisher=sin_publisher, buffer_size=2250)
    mod_data_source = DataSource(publisher=mod_publisher, buffer_size=2250)

    # Bind the data sources to their publishers
    sin_data_source.bind()
    mod_data_source.bind()

    #--------------------------------------------------------------------------
    # Plot Generation
    #--------------------------------------------------------------------------
    sin_index = ArrayDataSource([])
    sin_value = ArrayDataSource([])

    mod_index = ArrayDataSource([])
    mod_value = ArrayDataSource([])

    x_mapper = LinearMapper(range=DataRange1D(sin_index))
    y_mapper = LinearMapper(range=DataRange1D(sin_value))

    y_mapper.range.low_setting = -2.2
    y_mapper.range.high_setting = 2.2

    sin_line_plot = LinePlot(
        index=sin_index, value=sin_value, index_mapper=x_mapper, 
        value_mapper=y_mapper, color='darkblue',
    )
Пример #40
0
 def test_data_size(self):
     # We know that ArrayDataTestCase always returns the exact length of
     # its data
     myarray = arange(913)
     data_source = ArrayDataSource(myarray)
     self.assertEqual(len(myarray), data_source.get_size())
Пример #41
0
 def test_data_size(self):
     # We know that ScalarData always returns the exact length of its data
     myarray = arange(913)
     sd = ArrayDataSource(myarray)
     self.assert_(len(myarray) == sd.get_size())
     return
Пример #42
0
 def _plot_default(self):
     plotdata = ArrayPlotData()
     plot = MapPlot(plotdata,
                    auto_grid=False,
                    bgcolor=self.land_color)
     plot.x_axis.visible = False
     plot.y_axis.visible = False
     plot.padding = (0, 0, 0, 0)
     plot.border_visible = False
     index_mapper = LinearMapper(range=plot.index_range)
     value_mapper = LinearMapper(range=plot.value_range)
     if self.model.lake is not None:
         line_lengths = [l.length for l in self.model.lake.shoreline]
         idx_max = line_lengths.index(max(line_lengths))
         for num, l in enumerate(self.model.lake.shoreline):
             line = np.array(l.coords)
             x = line[:,0]
             y = line[:,1]
             # assume that the longest polygon is lake, all others islands
             if num == idx_max:
                 color = self.lake_color
             else:
                 color = self.land_color
             polyplot = PolygonPlot(index=ArrayDataSource(x),
                                    value=ArrayDataSource(y),
                                    edge_color=self.shore_color,
                                    face_color=color,
                                    index_mapper=index_mapper,
                                    value_mapper=value_mapper)
             plot.add(polyplot)
     for num, line in enumerate(self.survey_lines):
         coords = np.array(line.navigation_line.coords)
         x = coords[:,0]
         y = coords[:,1]
         x_key = 'x-line' + str(num)
         y_key = 'y-line' + str(num)
         plotdata.set_data(x_key, x)
         plotdata.set_data(y_key, y)
         self.line_plots[line.name] = plot.plot((x_key, y_key),
                                                color=self.line_color)
     for core in self.model.core_samples:
         x, y = core.location
         scatterplot = ScatterPlot(index=ArrayDataSource([x]),
                                    value=ArrayDataSource([y]),
                                    marker='circle',
                                    color=self.core_color,
                                    outline_color=self.core_color,
                                    index_mapper=index_mapper,
                                    value_mapper=value_mapper)
         plot.add(scatterplot)
     self._set_line_colors()
     if self.model.lake is not None:
         x_min, y_min, x_max, y_max = self.model.lake.shoreline.bounds
         index_mapper.range.high = x_max
         index_mapper.range.low = x_min
         value_mapper.range.high = y_max
         value_mapper.range.low = y_min
     plot.tools.append(PanTool(plot))
     plot.tools.append(ZoomTool(plot))
     self.line_select_tool = LineSelectTool(plot, line_plots=self.line_plots)
     # single click in map sets 'select point':  toggle in selected lines
     self.line_select_tool.on_trait_event(self.select_point, 'select_point')
     # double click in map sets 'current point': change current survey line
     self.line_select_tool.on_trait_event(self.current_point, 'current_point')
     plot.tools.append(self.line_select_tool)
     return plot
Пример #43
0
 def test_bounds_length_zero(self):
     # this is special-cased in the code, so exercise the code path
     data_source = ArrayDataSource(array([]))
     bounds = data_source.get_bounds()
     # XXX this is sort of inconsistent with test_bounds_all_nans()
     self.assertEqual(bounds, (0, 0))
Пример #44
0
    def test_get_data_mask_no_data(self):
        data_source = ArrayDataSource(None)

        data, mask = data_source.get_data_mask()
        assert_array_equal(data, 0.0)
        assert_array_equal(mask, True)
Пример #45
0
 def test_bounds_some_nan(self):
     data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3]))
     bounds = data_source.get_bounds()
     self.assertEqual(bounds, (0, 18))
Пример #46
0
def create_timechart_container(project):
    """ create a vplotcontainer which connects all the inside plots to synchronize their index_range """

    # find index limits
    low = 1 << 64
    high = 0
    for i in range(len(project.c_states)):
        if len(project.c_states[i].start_ts):
            low = min(low, project.c_states[i].start_ts[0])
            high = max(high, project.c_states[i].end_ts[-1])
        if len(project.p_states[i].start_ts):
            low = min(low, project.p_states[i].start_ts[0])
            high = max(high, project.p_states[i].start_ts[-1])
    for tc in project.processes:
        if len(tc.start_ts):
            low = min(low, tc.start_ts[0])
            high = max(high, tc.end_ts[-1])
    project.process_stats(low, high)
    if low > high:
        low = 0
        high = 1
    # we have the same x_mapper/range for each plots
    index_range = DataRange1D(low=low, high=high)
    index_mapper = LinearMapper(range=index_range, domain_limit=(low, high))
    value_range = DataRange1D(low=0,
                              high=project.num_cpu * 2 + project.num_process)
    value_mapper = LinearMapper(range=value_range,
                                domain_limit=(0, project.num_cpu * 2 +
                                              project.num_process))
    index = ArrayDataSource(array((low, high)), sort_order="ascending")
    plot = tcPlot(index=index,
                  proj=project,
                  bgcolor="white",
                  padding=(0, 0, 0, 40),
                  use_backbuffer=True,
                  fill_padding=True,
                  value_mapper=value_mapper,
                  index_mapper=index_mapper,
                  line_color="black",
                  render_style='hold',
                  line_width=1)
    plot.lowest_i = low
    plot.highest_i = high
    project.on_trait_change(plot.invalidate, "plot_redraw")
    project.on_trait_change(plot.invalidate, "selected")
    max_process = 50
    if value_range.high > max_process:
        value_range.low = value_range.high - max_process
    # Attach some tools
    plot.tools.append(tools.myPanTool(plot, drag_button='left'))
    zoom = tools.myZoomTool(component=plot,
                            tool_mode="range",
                            always_on=True,
                            axis="index",
                            drag_button=None,
                            zoom_to_mouse=True,
                            x_max_zoom_factor=float("inf"),
                            x_min_zoom_factor=float("-inf"))
    plot.tools.append(zoom)

    plot.range_selection = tools.myRangeSelection(plot, resize_margin=3)
    plot.tools.append(plot.range_selection)
    plot.overlays.append(
        RangeSelectionOverlay(component=plot,
                              axis="index",
                              use_backbuffer=True))

    axe = PlotAxis(orientation='bottom',
                   title='time',
                   mapper=index_mapper,
                   component=plot)
    plot.underlays.append(axe)
    plot.options.connect(plot)
    plot.range_tools.connect(plot)
    return plot
Пример #47
0
    def get_plot_component(self):
        # Create the array plot data that will feed our plots
        data = self.model.data
        plot_data = ArrayPlotData(
            index=data['dates'],
            close=data['close'],
            volume=data['volume'],
        )
        self.plot_data = plot_data

        # Need to make the FilledLinePlot manually since Plot doesn't
        # support that plot type.
        times = ArrayDataSource(data['dates'])
        prices = ArrayDataSource(data['close'])
        close_plot = FilledLinePlot(
            index=times,
            value=prices,
            index_mapper=LinearMapper(range=DataRange1D(times)),
            value_mapper=LinearMapper(range=DataRange1D(prices)),
            edge_color='blue',
            face_color='paleturquoise',
            bgcolor='white',
            border_visible=True)
        close_plot.padding = [40, 15, 15, 20]
        self.close_plot = close_plot

        # The second plotter object which generates our candle plot
        plotter2 = Plot(data=plot_data)
        low_plot = plotter2.plot(('index', 'close'), )[0]
        low_plot.height = 100
        low_plot.resizable = 'h'
        low_plot.bgcolor = 'white'
        low_plot.border_visible = True
        low_plot.padding = [40, 15, 15, 20]
        low_plot.color = 'darkred'
        low_plot.line_width = 1.5
        self.low_plot = low_plot

        # The third plotter for the bar plot.
        plotter3 = Plot(data=plot_data)
        bar_plot = plotter3.plot(('index', 'volume'), type='bar')[0]
        bar_plot.height = 100
        bar_plot.resizable = 'h'
        bar_plot.bgcolor = 'white'
        bar_plot.border_visible = True
        bar_plot.padding = [40, 15, 15, 20]
        bar_plot.line_color = 'transparent'
        bar_plot.fill_color = 'black'
        bar_plot.bar_width = 3.0
        bar_plot.bar_width_type = 'screen'
        bar_plot.antialias = False
        bar_plot.index_mapper = low_plot.index_mapper
        self.bar_plot = bar_plot

        for plot in (close_plot, low_plot, bar_plot):
            ticker = ScalesTickGenerator(scale=CalendarScaleSystem())
            bottom_axis = PlotAxis(plot,
                                   orientation='bottom',
                                   tick_generator=ticker)
            plot.overlays.append(bottom_axis)
            plot.overlays.append(PlotAxis(plot, orientation='left'))
            hgrid, vgrid = add_default_grids(plot)
            vgrid.tick_generator = bottom_axis.tick_generator

        def vol_label_formatter(val):
            return '%.1E' % val

        bar_plot.overlays[-1].tick_label_formatter = vol_label_formatter

        container = VPlotContainer(
            bgcolor=(240 / 255., 240 / 255., 240 / 255., 1.0),
            spacing=20,
            padding=20,
            fill_padding=True,
            stack_order='top_to_bottom',
            use_back_buffer=True,
        )

        container.add(close_plot)
        container.add(low_plot)
        container.add(bar_plot)

        close_plot.controller = RangeSelection(close_plot)
        zoom_overlay = ZoomOverlay(source=close_plot,
                                   destination=low_plot,
                                   other=bar_plot)
        container.overlays.append(zoom_overlay)

        return container