Example #1
0
 def plotWord(self,diagram,word,w,h,col,x,y,flip):
     self.plots.append((x,y,w,h))
     r = rectangle(x,y,w,h,fill="#FFF")
     diagram.add(r)
     fs = h*0.8
     tl = w*0.8
     if flip:
         fs = w*0.8
         tl = h*0.8
     t = text(x+w*0.1,y+h*0.1,word)
     t.addStyle("text-anchor","start")
     t.addAttr("dominant-baseline","hanging")
     t.addAttr("font-size",fs)
     t.addAttr("textLength",tl)
     t.addAttr("fill",col)
     t.addAttrs(self.text_attributes)
     if flip:
         t.addAttr("writing-mode","tb")
     diagram.add(t)
Example #2
0
 def draw(self,d,ox,oy):
     legend_column_width = self.width / self.legend_columns
     legend_y = oy
     legend_x = ox - (self.width/2)
     col = 0
     for (category, colour) in self.palette:
         g = self.legend_font_height
         points = [(legend_x, legend_y), (legend_x + g, legend_y), (legend_x + g, legend_y + g),
                   (legend_x, legend_y + g)]
         d.add(polygon(points, colour, "black", 2))
         t = text(legend_x+1.5*g, legend_y+g/2, self.labels[category])
         t.addStyle("font-size", self.legend_font_height)
         t.addStyle("text-anchor", "start")
         t.addStyle("alignment-baseline", "middle")
         t.addStyles(self.legend_text_style)
         d.add(t)
         col += 1
         if col >= self.legend_columns:
             legend_y += 2 * g
             legend_x = ox - (self.width/2)
             col = 0
         else:
             legend_x += legend_column_width
Example #3
0
 def draw_subtree(self, diagram, data, xc, yc, w, h):
     if isinstance(data, tuple):
         r = rectangle(xc,
                       yc,
                       w,
                       h,
                       fill=self.palette_lookup[data[0]],
                       tooltip=self.labels[data[0]])
         diagram.add(r)
         fraction = data[1] / self.sumtotal
         t = text(xc + w * 0.02, yc + h * 0.02,
                  "%.2f" % (100 * fraction) + "%")
         t.addStyle("text-anchor", "start")
         t.addAttr("dominant-baseline", "hanging")
         t.addAttrs(self.text_attributes)
         diagram.add(t)
     else:
         totals = []
         for d in data:
             totals.append(self.total(d))
         sumtotal = sum(totals)
         if w < h:
             # divide vertically
             y = yc
             for idx in range(len(data)):
                 sh = h * (totals[idx] / sumtotal)
                 self.draw_subtree(diagram, data[idx], xc, y, w, sh)
                 y += sh
         else:
             x = xc
             for idx in range(len(data)):
                 sw = h * (totals[idx] / sumtotal)
                 self.draw_subtree(diagram, data[idx], x, yc, sw, h)
                 x += sw
         r = rectangle(xc, yc, w, h, stroke="black", stroke_width=4)
         diagram.add(r)
Example #4
0
    def draw(self, d, ox, oy):
        height = self.height / len(self.keys)

        ay = 0

        plot_width = self.width / len(self.axes)

        if len(self.axis_labels):
            ay = self.axis_label_height
            for axis in range(0, len(self.axes) + 1):
                axis_label_x = (ox - self.width / 2) + axis * plot_width
                axis_label_y = oy
                t = text(axis_label_x, axis_label_y, self.axis_labels[axis])
                t.addStyle("font-size", self.axis_label_height)
                if axis == 0:
                    pos = "start"
                elif axis == len(self.axes):
                    pos = "end"
                else:
                    pos = "middle"
                t.addStyle("text-anchor", pos)
                d.add(t)

        grp = group()
        d.add(grp)

        for axis in range(0, len(self.axes)):
            axis_x0 = (ox - self.width / 2) + axis * plot_width
            axis_x1 = (ox - self.width / 2) + (axis + 1) * plot_width

            points0 = self.axes[axis][0]
            points1 = self.axes[axis][1]

            state = None
            for idx in range(0, len(points0)):
                key = points0[idx]
                cat0 = self.data[key][axis]
                cat1 = self.data[key][axis + 1]
                oidx = points1.index(key)
                if state == None:
                    state = (cat0, cat1, (idx, idx), (oidx, oidx))
                else:
                    (pcat0, pcat1, (pidx_min, pidx_max), (poidx_min,
                                                          poidx_max)) = state
                    if cat0 == pcat0 and cat1 == pcat1:
                        state = (cat0, cat1, (pidx_min, idx),
                                 (min(oidx, poidx_min), max(oidx, poidx_max)))
                    else:
                        count = 1 + pidx_max - pidx_min
                        self.drawConnection(
                            d, grp, axis_x0, axis_x1, ay + oy, 100, height,
                            state,
                            self.getLabel(pcat0) + "=>" +
                            self.getLabel(pcat1) + "(%d seats)" % (count))
                        state = (cat0, cat1, (idx, idx), (oidx, oidx))
            if state != None:
                (pcat0, pcat1, (pidx_min, pidx_max), (poidx_min,
                                                      poidx_max)) = state
                count = 1 + pidx_max - pidx_min
                self.drawConnection(
                    d, grp, axis_x0, axis_x1, ay + oy, 100, height, state,
                    pcat0 + "=>" + pcat1 + "(%d seats)" % (count))
Example #5
0
    def draw(self, diagram, ox, oy):
        xc = ox - self.width / 2
        yc = oy

        coords = {}

        nodes = self.data[0]
        links = self.data[1]

        node_links = {}

        distance = lambda x1, y1, x2, y2: sqrt((x1 - x2)**2 + (y1 - y2)**2)

        def clip(coords):
            (x, y, r) = coords
            if x < xc + r:
                x = xc + r
            if y < yc + r:
                y = yc + r
            if x > xc + self.width - r:
                x = xc + self.width - r
            if y > yc + self.height - r:
                y = yc + self.height - r
            return (x, y, r)

        for (nodeid0, nodeid1, weight) in links:
            if nodeid0 not in node_links:
                node_links[nodeid0] = []
            if nodeid1 not in node_links:
                node_links[nodeid1] = []
            node_links[nodeid0].append(nodeid1)
            node_links[nodeid1].append(nodeid0)

        for (nodeid, cat, value) in nodes:
            frac = value / self.sumtotal
            area = self.width * self.height * 0.25 * frac
            r = sqrt(area / pi)
            cx = xc + r + (self.width - 2 * r) * random.random()
            cy = yc + r + (self.height - 2 * r) * random.random()
            coords[nodeid] = (cx, cy, r)

        c1 = 2
        c3 = 1
        c4 = 0.1
        c5 = 100
        iters = 50000

        for iter in range(iters):
            forces = {}
            for (nodeid, cat, value) in nodes:
                forces[nodeid] = (0, 0)
                (nx, ny, nr) = coords[nodeid]
                if nodeid in node_links:
                    for adjid in node_links[nodeid]:
                        (ax, ay, adjr) = coords[adjid]
                        c2 = (nr + adjr) * 2
                        d = distance(nx, ny, ax, ay)
                        f = c1 * log(d / c2)
                        fx = ((ax - nx) / d) * f * c4
                        fy = ((ay - ny) / d) * f * c4
                        forces[nodeid] = (forces[nodeid][0] + fx,
                                          forces[nodeid][1] + fy)
                for otherid in coords:
                    if otherid != nodeid:
                        (ox, oy, otherr) = coords[otherid]
                        d = distance(nx, ny, ox, oy)
                        f = c3 / (d**2)
                        fx = ((nx - ox) / d) * f * c5
                        fy = ((ny - oy) / d) * f * c5
                        forces[nodeid] = (forces[nodeid][0] + fx,
                                          forces[nodeid][1] + fy)

            for nodeid in coords:
                coords[nodeid] = (coords[nodeid][0] + forces[nodeid][0],
                                  coords[nodeid][1] + forces[nodeid][1],
                                  coords[nodeid][2])
                coords[nodeid] = clip(coords[nodeid])

        for (nodeid0, nodeid1, weight) in links:
            (x1, y1, r1) = coords[nodeid0]
            (x2, y2, r2) = coords[nodeid1]
            l = line(x1, y1, x2, y2, self.getLinkColour(weight), 3)
            diagram.add(l)

        for (nodeid, cat, value) in nodes:
            (cx, cy, r) = coords[nodeid]
            col = self.palette_lookup[cat]
            circ = circle(cx, cy, r, col)
            circ.addAttr("stroke", "#EEE")
            circ.addAttr("stroke-width", 4)

            diagram.add(circ)
            if nodeid in self.labels:
                label = self.labels[nodeid]
                length = len(label)
                t = text(cx, cy, label)
                font_height = 2 * r * 0.8 / length
                text_length = font_height * length
                t.addAttr("textLength", text_length)
                t.addAttr("font-size", font_height)
                t.addAttrs(self.text_attributes)
                diagram.add(t)
Example #6
0
    def renderGrid(self, diagram, ox, oy, dlength, scores):
        rangle = radians(30)
        off_sm = dlength * sin(rangle)
        off_lg = dlength * cos(rangle)
        hx = ox
        labels = []
        js = javascript_snippet("""
function toggleVisibility(cls) {
    var found = document.getElementsByClassName(cls);
    for(var idx=0; idx<found.length; idx++) {
        if (found[idx].getAttribute("visibility") == "hidden") {
            found[idx].setAttribute("visibility","visible");
        } else {
            found[idx].setAttribute("visibility","hidden");
        }
    }
}
""")
        diagram.add(js)
        for xc in range(0, self.gx):
            hy = oy
            for yc in range(0, self.gy):
                y = hy
                x = hx
                if yc % 2 == 1:
                    x += off_lg
                poly = self.hexagon((x, y), dlength, "#E0E0E0",
                                    (128, 128, 128),
                                    str(xc) + "_" + str(yc))
                poly.addStyle("stroke", "grey")
                poly.addStyle("stroke-width", "3")
                cls = str(xc) + "_" + str(yc)
                poly.addAttr("onclick", "toggleVisibility(\"" + cls + "\")")
                diagram.add(poly)

                centroid = self.plot.getWeights(self.plot.getOutput(xc, yc))
                assigned = scores[(xc, yc)]
                if assigned:
                    centroid_sum = sum(centroid)
                    theta = 0
                    cx = x
                    cy = y - dlength / 2
                    r1 = dlength * 0.5
                    r2 = dlength * 0.7
                    r3 = r2 + 10
                    for idx in range(0, len(centroid)):
                        theta0 = theta
                        theta += 2 * pi * centroid[idx] / centroid_sum
                        s = sector(cx, cy, 0, r1, theta0, theta,
                                   self.plot.palette[idx][0])
                        s.addStyle("fill", self.plot.palette[idx][1])
                        s.addAttr("onclick",
                                  "toggleVisibility(\"" + cls + "\")")
                        diagram.add(s)

                    assigned = sorted(assigned, key=lambda x: x[1])
                    theta = 0
                    step = pi * 2 / len(assigned)
                    if step > 1.0:
                        step = 1.0

                    for (label, colour) in assigned:
                        px = cx + r2 * cos(theta)
                        py = cy + r2 * sin(theta)
                        pxl = cx + r3 * cos(theta)
                        pyl = cy + r3 * sin(theta)
                        c = circle(px, py, dlength * 0.1, colour, label)
                        t = text(pxl, pyl, label)
                        t.addAttr("dominant-baseline", "middle")
                        t.addStyle("paint-order", "stroke")
                        t.addStyle("fill", colour)
                        t.addStyle("stroke-width", "10px")
                        t.addStyle("stroke", "white")
                        if theta > pi / 2 and theta < pi * 1.5:
                            t.addStyle("text-anchor", "end")
                            t.setRotation(theta - pi)
                        else:
                            t.addStyle("text-anchor", "start")
                            t.setRotation(theta)
                        t.addAttr("visibility", "hidden")
                        t.addAttr("class", cls)
                        diagram.add(c)
                        labels.append(t)
                        theta += step

                hy = hy + dlength + off_sm
            hx = hx + 2 * off_lg
        for label in labels:
            diagram.add(label)
        return (ox + off_lg + self.gx * (2 * off_lg) + 10,
                oy + off_sm + (self.gy) * (dlength + off_sm) + 10)