Repository URL to install this package:
Version:
4.8.0 ▾
|
chaco
/
base_candle_plot.py
|
---|
from __future__ import with_statement
# Major library imports
from numpy import array, column_stack
# Enthought library imports
from enable.api import ColorTrait
from traits.api import Bool, Float, Int, List, Property, Trait
# Chaco imports
from .base_xy_plot import BaseXYPlot
# TODO: allow to set the width of the bar
def Alias(name):
return Property(lambda obj: getattr(obj, name),
lambda obj, val: setattr(obj, name, val))
class BaseCandlePlot(BaseXYPlot):
""" Represents the base class for candle- and bar-type plots that are
multi-valued at each index point, and optionally have an extent in the
index dimension.
Implements the rendering logic and centralizes a lot of the visual
attributes for these sorts of plots. The gather and culling and
clipping of data is up to individual subclasses.
"""
#------------------------------------------------------------------------
# Appearance traits
#------------------------------------------------------------------------
# The fill color of the marker.
color = ColorTrait("black")
# The fill color of the bar
bar_color = Alias("color")
# The color of the rectangular box forming the bar.
bar_line_color = Alias("outline_color")
# The color of the stems reaching from the bar ends to the min and max
# values. Also the color of the endcap line segments at min and max. If
# None, this defaults to **bar_line_color**.
stem_color = Trait(None, None, ColorTrait("black"))
# The color of the line drawn across the bar at the center values.
# If None, this defaults to **bar_line_color**.
center_color = Trait(None, None, ColorTrait("black"))
# The color of the outline to draw around the bar.
outline_color = ColorTrait("black")
# The thickness, in pixels, of the outline to draw around the bar. If
# this is 0, no outline is drawn.
line_width = Float(1.0)
# The thickness, in pixels, of the stem lines. If None, this defaults
# to **line_width**.
stem_width = Trait(None, None, Int(1))
# The thickeness, in pixels, of the line drawn across the bar at the
# center values. If None, this defaults to **line_width**.
center_width = Trait(None, None, Int(1))
# Whether or not to draw bars at the min and max extents of the error bar
end_cap = Bool(True)
#------------------------------------------------------------------------
# Private traits
#------------------------------------------------------------------------
# Override the base class definition of this because we store a list of
# arrays and not a single array.
_cached_data_pts = List()
#------------------------------------------------------------------------
# BaseXYPlot interface
#------------------------------------------------------------------------
def get_screen_points(self):
# Override the BaseXYPlot implementation so that this is just
# a pass-through, in case anyone calls it.
pass
#------------------------------------------------------------------------
# Protected methods (subclasses should be able to use these directly
# or wrap them)
#------------------------------------------------------------------------
def _render(self, gc, right, left, min, bar_min, center, bar_max, max):
stack = column_stack
with gc:
widths = right - left
bar_vert_center = left + widths / 2.0
# Draw the stem lines for min to max. Draw these first so we can
# draw the boxes on top.
# A little tricky: we need to account for cases when either min or max
# are None. To do this, just draw to bar_min or from bar_max instead
# of drawing a single line from min to max.
if min is not None or max is not None:
if self.stem_color is None:
stem_color = self.outline_color_
else:
stem_color = self.stem_color_
gc.set_stroke_color(stem_color)
if self.stem_width is None:
stem_width = self.line_width
else:
stem_width = self.stem_width
gc.set_line_width(stem_width)
if min is None:
gc.line_set(stack((bar_vert_center, bar_max)), stack((bar_vert_center, max)))
if self.end_cap:
gc.line_set(stack((left, max)), stack((right, max)))
elif max is None:
gc.line_set(stack((bar_vert_center, min)), stack((bar_vert_center, bar_min)))
if self.end_cap:
gc.line_set(stack((left, min)), stack((right, min)))
else:
gc.line_set(stack((bar_vert_center, min)), stack((bar_vert_center, max)))
if self.end_cap:
gc.line_set(stack((left, max)), stack((right, max)))
gc.line_set(stack((left, min)), stack((right, min)))
gc.stroke_path()
# Draw the candlestick boxes
boxes = stack((left, bar_min, widths, bar_max - bar_min))
gc.set_antialias(False)
gc.set_stroke_color(self.outline_color_)
gc.set_line_width(self.line_width)
gc.rects(boxes)
if self.color in ("none", "transparent", "clear"):
gc.stroke_path()
else:
gc.set_fill_color(self.color_)
gc.draw_path()
# Draw the center line
if center is not None:
if self.center_color is None:
gc.set_stroke_color(self.outline_color_)
else:
gc.set_stroke_color(self.center_color_)
if self.center_width is None:
gc.set_line_width(self.line_width)
else:
gc.set_line_width(self.center_width)
gc.line_set(stack((left, center)), stack((right, center)))
gc.stroke_path()
def _render_icon(self, gc, x, y, width, height):
min = array([y + 1])
max = array([y + height - 1])
bar_min = array([y + height / 3])
bar_max = array([y + height - (height / 3)])
center = array([y + (height / 2)])
self._render(gc, array([x+width/4]), array([x+3*width/4]), min, bar_min, center, bar_max, max)