Source

tw2.protovis.custom / tw2 / protovis / custom / widgets.py

"""
TODO
"""

import tw2.core as twc
import tw2.protovis.core as twp
from tw2.protovis.core import pv

class js(twc.JSSymbol):
    def __init__(self, src):
        super(js, self).__init__(src=src)

class SparkLine(twp.PVWidget):
    """
    A sparkline is a word-sized data visualization, allowing visual
    representations of data to be embedded directly in prose. This avoids
    any interruption in the flow of text, with the data presented in
    descriptive context. Sparklines can be used where space is limited,
    unlike standalone figures.
    """
    p_dots = twc.Param('dots', default=False)

    def prepare(self):
        self.init_js = js(
            """
            var dots = %i;
            var data = %s;
            var n = data.length;
            var w = n,
                h = %i,
                min = pv.min.index(data),
                max = pv.max.index(data);
            """ % (self.p_dots, self.p_data, self.p_height))
       
        self.p_width = len(self.p_data)
        self.setupRootPanel()
        self.margin(2)

        self.add(pv.Line) \
          .data(js('data')) \
          .left(js('pv.Scale.linear(0, n - 1).range(0, w).by(pv.index)')) \
          .bottom(js('pv.Scale.linear(data).range(0, h)')) \
          .strokeStyle("#000") \
          .lineWidth(1) \
        .add(pv.Dot) \
          .visible(
              js('function() (dots && this.index==0) || this.index==n - 1')) \
          .strokeStyle(None) \
          .fillStyle("brown") \
          .radius(2) \
        .add(pv.Dot) \
          .visible(
              js('function() dots && (this.index==min || this.index==max)')) \
          .fillStyle("steelblue");

class SparkBar(twp.PVWidget):
    """ A sparkbar is just like a sparkline, but,... you know. """
    def prepare(self):
        self.init_js = js(
            """
            var data = %s;
            var n = data.length;
            var w = n,
                h = %i;
            """ % (self.p_data, self.p_height))
       
        self.setupRootPanel()

        self.add(pv.Bar) \
          .data(js('data'))\
          .width(4)\
          .left(js('function() 5 * this.index'))\
          .height(js('function(d) Math.round(h * d)'))\
          .bottom(0)

class StreamGraph(twp.PVWidget):
    """
    Streamgraphs are a generalization of stacked area graphs where the
    baseline is free. By shifting the baseline, it is possible to minimize
    the change in slope (or "wiggle") in individual series, thereby making
    it easier to perceive the thickness of any given layer across the data.
    Byron & Wattenberg describe several streamgraph algorithms in "Stacked
    Graphs--Geometry & Aesthetics", several of which are implemented by
    pv.Layout.Stack.
    """
    def prepare(self):
        self.init_js = js(
            """
            var n = 20, m = 400;
            var data = %s,
                w = %i,
                h = %i,
                x = pv.Scale.linear(0, m - 1).range(0, w),
                y = pv.Scale.linear(0, 2 * n).range(0, h);
            """ % (self.p_data, self.p_width, self.p_height))
        
        self.setupRootPanel()

        self.add(pv.Layout.Stack)\
                .layers(js('data'))\
                .order('inside-out')\
                .offset('wiggle')\
                .x(js('x.by(pv.index)'))\
                .y(js('y'))\
              .layer.add(pv.Area)\
                .fillStyle(js('pv.ramp("#aad", "#556").by(Math.random)'))\
                .strokeStyle(js('function() this.fillStyle().alpha(0.5)'))

class BubbleChart(twp.PVWidget):
    """
    Bubble charts encode data in the area of circles. Although less
    perceptually accurate than bar charts, they can pack hundreds of
    values into a small space. A similar technique is the Dorling
    cartogram, where circles are positioned according to geography rather
    than arbitrarily. Here we compare the file sizes of the Flare
    visualization toolkit.
    """
    def prepare(self):
        self.init_js = js(
            """
            var data = pv.nodes(%s);
            var format = pv.Format.number();
            """ % (self.p_data))
        
        self.setupRootPanel()

        self.add(pv.Layout.Pack) \
            .top(-50) \
            .bottom(-50) \
            .nodes(js('data')) \
            .size(js('function(d) d.nodeValue.value')) \
            .spacing(0) \
            .order(None) \
          .node.add(pv.Dot) \
            .fillStyle(
        js('pv.Colors.category20().by(function(d) d.nodeValue.group)')) \
            .strokeStyle(js('function() this.fillStyle().darker()')) \
            .visible(js('function(d) d.parentNode')) \
            .title(js('function(d) d.nodeValue.name + ": " + format(d.nodeValue.value)')) \
          .anchor("center").add(pv.Label) \
            .text(
        js('function(d) d.nodeValue.text.substring(0, Math.sqrt(d.nodeValue.value/25.0) >> 4)'))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.