def demoPIL(html): print('be patient, this is a little slow...') import piddlePIL pc = piddlePIL.PILCanvas((800, 600), 'HTMLPiddler') pc.drawLine(0, 0, 100, 80, color=piddle.green) pc.drawRect(50, 50, 750, 550, edgeColor=piddle.pink) ptt = HTMLPiddler(html, (100, 80), (50, 750)) ptt.renderOn(pc) pc.save(format='tif')
def dendrogram(self, labels, width=500, height=None, margin=20, hook=40, line_size=2.0, cluster_colors=[], canvas=None, line_width=1, color_mode=0, incremental_height=1, matr=[], g_lines=0, additional_labels=[], additional_matr=[], add_tags=[], adwidth=1.0, plot_gains=0, gains=[], gain_width=70, plot_ints=0, right_align=0, im=None): # prevent divide-by-zero... if len(labels) < 2: return canvas if plot_ints or (plot_gains and len(gains) == 0): # the gains have been proposed but not calculated if len(gains) > 0: warnings.warn( 'Ignoring the given gains: need to refer to the interaction matrix.' ) gains = [] # discretized gains mv = 1.0 / max(1e-6, max(im.gains)) for v in im.gains: gains.append( v * mv ) # normalize with respect to the best attribute from correlation analysis. if len(gains) > 0: # fix the widths gain_l = [] for i in range(self.n): gain_l.append(gains[i]) max_intlen = 0.0 if plot_ints: # include the interactions between all pairs intlist = [] for i in range(self.n - 1): idx1 = self.order[i] - 1 idx2 = self.order[i + 1] - 1 ig = im.way3[(min(idx1, idx2), max(idx1, idx2), -1)].InteractionInformation() if gains[idx1] < gains[idx2]: idx1, idx2 = idx2, idx1 if ig > 0: max_intlen = max(max_intlen, gain_width * ig * mv) gain_l[idx1] += ig * mv # possibly new maximum width intlist.append((idx1, ig * mv, 0.0)) else: intlist.append((idx2, ig * mv, 1.0)) else: intlist = [] ## ADJUST DIMENSIONS ### if canvas == None: tcanvas = piddlePIL.PILCanvas() else: tcanvas = canvas normal = piddle.Font(face=_defaultfont) bold = piddle.Font(face=_defaultfont, bold=1) if height == None: # compute the height lineskip = int(line_size * tcanvas.fontHeight(normal) + 1) lines = len(labels) - 1 if len(additional_labels) > 0: lines += 1 + len(additional_labels) height = int(2.0 * margin + lineskip * (lines) + tcanvas.fontHeight(normal) + 1) else: # compute lineskip lineskip = (height - 2.0 * margin - tcanvas.fontHeight(normal)) / (len(labels) - 1) maxlabel = 0.0 spacew = tcanvas.stringWidth(" ", font=normal) swids = [] for i in range(len(labels)): swid = tcanvas.stringWidth(labels[i], font=normal) swids.append(swid + spacew) if len(gains) > 0: assert (len(gains) == len(labels)) swid += spacew + gain_l[i] * gain_width maxlabel = max(maxlabel, swid) maxswid = max(swids) if canvas == None: canvas = piddlePIL.PILCanvas(size=(width, height)) if len(matr) > 0: block = lineskip / 2 - 1 else: block = 0 _colorize = _color_picker(color_mode) ### EXTRACT THE DENDROGRAM ### vlines = [] # vertical lines (cluster) hlines = [] # horizontal lines (clusters) origins = [0.0] * self.n # text positions xpositions = [0.0] * self.n # cluster x positions (height) ypositions = [0] * self.n # cluster y positions (average element) attcolors = [0] * self.n y = margin for i in range(len(labels)): # self.order identifies the label at a particular row ypositions[self.n - self.order[i]] = y y += lineskip xpositions.append("sentry") ypositions.append("sentry") p = self.n # bottom-up construction height = 0.0 displacement = 0.0 for i in range(self.n - 1): if len(cluster_colors) == self.n - 1: coloV = _colorize(cluster_colors[i][0]) coloH = _colorize(cluster_colors[i][1]) else: # no color information coloH = coloV = piddle.black # obtain the height if incremental_height: nheight = min(xpositions[p + self.merging[i][0]], xpositions[p + self.merging[i][1]]) nheight -= self.height[i] displacement = min(displacement, nheight) else: height -= self.height[i] nheight = height vlines.append((nheight, ypositions[p + self.merging[i][0]], ypositions[p + self.merging[i][1]], coloV)) avg = 0.0 for j in self.merging[i]: # record text origins v = ypositions[p + j] if j < 0: origins[-1 - j] = nheight attcolors[-1 - j] = coloH else: # create the cluster lines hlines.append((v, xpositions[p + j], nheight, coloH)) avg += v # recompute the average height of new cluster ypositions.append(0.5 * avg) xpositions.append(nheight) #print displacement ### DRAWING ### offset = width - maxlabel - hook - 2 * margin if len(matr) > 0: offset -= 2 * (len( matr[0] )) * adwidth * block + 2 * block # correct the right-hand side hs = (offset - margin) / (height - displacement) # height scaling if incremental_height: hs = -hs halfline = canvas.fontAscent(font=normal) / 2.0 # print line-guides if g_lines and len(matr) == len(labels): colo = piddle.Color(0.9, 0.9, 0.9) y = margin s = len(matr[0]) sx1 = width - margin - block sx2 = width - margin - 2 * (len(matr[0])) * adwidth * block - block canvas.drawLine(sx1, y - block - 1, sx2, y - block - 1, colo, width=1) x2 = width - margin - block for i in range(len(labels)): idx = self.order[i] - 1 x1 = offset + hook - hs * (origins[idx]) + tcanvas.stringWidth( labels[idx], font=normal) + 4 canvas.drawLine(x1, y, sx2, y, colo, width=1) canvas.drawLine(sx1, y + block + 1, sx2, y + block + 1, colo, width=1) y += lineskip if len(additional_labels) > 0: y += lineskip canvas.drawLine(sx1, y - block - 1, sx2, y - block - 1, colo, width=1) for i in range(len(additional_labels)): x1 = offset + hook + 5 + tcanvas.stringWidth( additional_labels[i], font=normal) + 4 canvas.drawLine(x1, y, sx2, y, colo, width=1) canvas.drawLine(sx1, y + block + 1, sx2, y + block + 1, colo, width=1) y += lineskip # vertical guides for i in range(len(matr[0]) + 1): x = width - margin - (2 * (i) * adwidth * block) - block canvas.drawLine(x, margin - block, x, y - lineskip + block + 1, colo, width=1) # print names y = margin for i in range(len(labels)): # self.order identifies the label at a particular row idx = self.order[i] - 1 x = offset - hs * (origins[idx]) if labels[idx][0] == '*': canvas.drawString(labels[idx][1:], hook + x, y + halfline, font=bold) else: canvas.drawString(labels[idx], hook + x, y + halfline, font=normal) # draw the hook canvas.drawLine(x, y, x + hook * 0.8, y, attcolors[idx], width=line_width) GSERIF = 1.2 * line_width MULT = 1.2 * line_width XMULT = 0.6 * line_width XSERIF = 0.6 * line_width SWIDTH = 1 if len(gains) > 0: # draw the gain line if right_align: orig = width - margin - gain_width * gains[idx] - max_intlen else: orig = hook + x + swids[idx] if gain_width * gains[idx] >= 2.0 * MULT: canvas.drawLine(orig + MULT, y, orig + gain_width * gains[idx] - MULT, y, piddle.black, width=MULT) # actual line canvas.drawLine(orig, y, orig + gain_width * gains[idx], y, piddle.black, width=SWIDTH) # thin line canvas.drawLine(orig, y - GSERIF, orig, y + GSERIF, piddle.black, width=SWIDTH) #serif 1 canvas.drawLine(orig + gain_width * gains[idx], y - GSERIF, orig + gain_width * gains[idx], y + GSERIF, piddle.black, width=SWIDTH) #serif2 if len(intlist) > 0 and i > 0: (qidx, widt, cc) = intlist[i - 1] if right_align: nx = width - margin - max_intlen else: nx = offset - hs * (origins[qidx]) + hook + swids[ qidx] + gain_width * gains[qidx] ny = y - 0.5 * lineskip colo = _colorize(cc) if widt > 0: disp = XMULT seri = XSERIF else: disp = -XMULT seri = -XSERIF if abs(gain_width * widt) >= 2.0 * XMULT: canvas.drawLine(nx + disp, ny, nx + gain_width * widt - disp, ny, colo, width=XMULT) # actual line canvas.drawLine(nx + gain_width * widt - seri, ny - seri, nx + gain_width * widt, ny, colo, width=SWIDTH) # arrowpoint 1 canvas.drawLine(nx + gain_width * widt - seri, ny + seri, nx + gain_width * widt, ny, colo, width=SWIDTH) # arrowpoint 2 canvas.drawLine(nx, ny, nx + gain_width * widt, ny, colo, width=SWIDTH) # thin line canvas.drawLine(nx, ny - XSERIF, nx, ny + XSERIF, colo, width=SWIDTH) # serif 1 y += lineskip for i in range(len(additional_labels)): y += lineskip if additional_labels[i][0] == '*': canvas.drawString(additional_labels[i][1:], offset + hook + 5, y + halfline, font=bold) else: canvas.drawString(additional_labels[i], offset + hook + 5, y + halfline, font=normal) y += lineskip * 1.5 for i in range(len(add_tags)): wi = tcanvas.stringWidth(add_tags[i], font=normal) x = width - margin - 2 * (len(add_tags) - i - 0.5) * adwidth * block - block - wi / 2 canvas.drawString(add_tags[i], x, y + halfline, font=bold) # print lines for (y, x1, x2, colo) in hlines: canvas.drawLine(offset - (x1) * hs, y, offset - (x2) * hs, y, colo, width=line_width) vlines.reverse() # smaller clusters are more interesting for (x, y1, y2, colo) in vlines: canvas.drawLine(offset - (x) * hs, y1, offset - (x) * hs, y2, colo, width=line_width) ### MATRIX RENDERING ### if len(matr) == len(labels): y = margin for i in range(len(labels)): # print labels[i],matr[i] idx = self.order[i] - 1 mm = matr[idx] for j in range(len(mm)): # self.order identifies the label at a particular row x = width - margin - 2 * (len(mm) - j - 0.5) * adwidth * block - block v = 1 - mm[j] #if v < 254.0/255.0: colo = piddle.Color(v, v, v) canvas.drawRect(x - adwidth * block + 1, y - block, x + adwidth * block - 1, y + block, edgeColor=colo, fillColor=colo) y += lineskip for i in range(len(additional_matr)): y += lineskip mm = additional_matr[i] for j in range(len(mm)): x = width - margin - 2 * (len(mm) - j - 0.5) * adwidth * block - block v = 1 - mm[j] colo = piddle.Color(v, v, v) canvas.drawRect(x - adwidth * block + 1, y - block, x + adwidth * block - 1, y + block, edgeColor=colo, fillColor=colo) canvas.flush() return canvas
def Matrix(diss=[], hlabels=[], vlabels=[], sizing=[], margin=10, hook=10, block=None, line_size=2.0, color_mode=0, sizing2=[], canvas=None, multiplier=1.0): # prevent divide-by-zero... if len(hlabels) < 2: return canvas ## ADJUST DIMENSIONS ### if canvas == None: tcanvas = piddlePIL.PILCanvas() else: tcanvas = canvas normal = piddle.Font(face=_defaultfont) bold = piddle.Font(face=_defaultfont, bold=1) square = 0 if len(diss) > 0: yd = len(diss) if len(diss) == len(diss[0]): square = 1 xd = yd else: xd = len(diss[0]) else: yd = len(sizing) if len(sizing) == len(sizing[0]): square = 1 xd = yd else: xd = len(sizing[0]) if len(hlabels) == 0: hlabels = ["" for i in range(yd)] if len(vlabels) == 0: if square: vlabels = hlabels # vertical labels... else: vlabels = ["" for i in range(xd)] # compute the height lineskip = int(line_size * tcanvas.fontHeight(normal) + 1) labellen = [tcanvas.stringWidth(s, font=normal) for s in hlabels] vlabellen = [tcanvas.stringWidth(s, font=normal) for s in vlabels] maxlabelx = max(labellen) maxlabely = max(vlabellen) width = int(1 + 2.0 * margin + hook + maxlabelx + lineskip * (len(vlabels)) + tcanvas.fontHeight(normal)) height = int(1 + 2.0 * margin + hook + maxlabely + lineskip * (len(hlabels)) + tcanvas.fontHeight(normal)) if block == None: block = lineskip / 2 - 1 if canvas == None: canvas = piddlePIL.PILCanvas(size=(width, height)) _colorize = _color_picker(color_mode) ### DRAWING ### offsetx = maxlabelx + margin offsety = maxlabely + margin halfline = canvas.fontAscent(normal) / 2.0 for i in range(len(vlabels)): x2 = offsetx + lineskip * (i) + hook y2 = offsety + halfline - hook # vertical if vlabels[i][0] == '*': canvas.drawString(vlabels[i][1:], x2 + block + halfline, y2 + block, angle=90, font=bold) else: canvas.drawString(vlabels[i], x2 + block + halfline, y2 + block, angle=90, font=normal) # print names for i in range(len(hlabels)): # self.order identifies the label at a particular row x = offsetx - labellen[i] y = offsety + lineskip * (i + 1) + halfline canvas.drawString(hlabels[i], x, y, font=normal) for j in range(len(vlabels)): x = offsetx + hook + lineskip * (j) + block y = offsety + lineskip * (i + 1) if len(sizing) == 0: ss = 1.0 else: ss = min(1, sizing[i][j]) ss *= multiplier if len(diss) > 0: colo = _colorize(diss[i][j]) canvas.drawRect(x - ss * block, y - ss * block, x + ss * block, y + ss * block, edgeColor=colo, fillColor=colo, edgeWidth=0.5) if len(sizing2) > 0: ss = sizing2[i][j] ss *= multiplier canvas.drawRect(x - ss * block, y - ss * block, x + ss * block, y + ss * block, edgeColor=piddle.black, fillColor=None, edgeWidth=0.5) canvas.flush() return canvas
def YDensityMatrix(diss=[], hlabels=[], vlabels=[], margin=10, hook=10, block=None, line_size=2.0, ysize=100, ticklen=3, color_mode=0, canvas=None): # prevent divide-by-zero... if len(hlabels) < 2: return canvas ## ADJUST DIMENSIONS ### if canvas == None: tcanvas = piddlePIL.PILCanvas() else: tcanvas = canvas normal = piddle.Font(face=_defaultfont) bold = piddle.Font(face=_defaultfont, bold=1) if len(diss) > 0: yd = len(diss) xd = len(diss[0]) if len(vlabels) == 0: vlabels = ["" for i in range(xd)] else: assert (xd == len(vlabels)) if len(hlabels) < 2: hlabels = ["0.0", "1.0"] dh = ysize / float(len(hlabels) - 1) # compute the height lineskip = int(line_size * tcanvas.fontHeight(normal) + 1) labellen = [tcanvas.stringWidth(s, font=normal) for s in hlabels] vlabellen = [tcanvas.stringWidth(s, font=normal) for s in vlabels] maxlabelx = max(labellen) maxlabely = max(vlabellen) width = int(1 + 2.0 * margin + hook + maxlabelx + lineskip * (len(vlabels)) + tcanvas.fontHeight(normal)) height = int(1 + 2.0 * margin + hook + maxlabely + ysize) if block == None: block = lineskip / 2 - 1 if canvas == None: canvas = piddlePIL.PILCanvas(size=(width, height)) _colorize = _color_picker(color_mode) ### DRAWING ### offsetx = maxlabelx + margin offsety = maxlabely + margin halfline = canvas.fontAscent(normal) / 2.0 for i in range(len(vlabels)): x2 = offsetx + lineskip * (i) + hook y2 = offsety # vertical if vlabels[i][0] == '*': canvas.drawString(vlabels[i][1:], x2 + block + halfline, y2, angle=90, font=bold) else: canvas.drawString(vlabels[i], x2 + block + halfline, y2, angle=90, font=normal) for i in range(len(hlabels)): x = offsetx - labellen[i] y = offsety + hook + i * dh # horizontal if hlabels[-i - 1][0] == '*': canvas.drawString(hlabels[-i - 1][1:], x, y + halfline, font=bold) else: canvas.drawString(hlabels[-i - 1], x, y + halfline, font=normal) # tick canvas.drawLine(offsetx - ticklen + hook, y, offsetx + hook, y, width=1) dy = ysize / float(len(diss)) for i in range(len(diss)): for j in range(len(vlabels)): x = offsetx + hook + lineskip * (j) + block y = offsety + hook + i * dy colo = _colorize(diss[i][j]) canvas.drawRect(x - block, y, x + block, y + dy, edgeColor=colo, fillColor=colo) canvas.flush() return canvas
def matrix(self, labels, diss, margin=10, hook=10, block=None, line_size=2.0, att_colors=[], canvas=None, color_mode=0, diagonal=0): # prevent divide-by-zero... if len(labels) < 2: return canvas ## ADJUST DIMENSIONS ### if canvas == None: tcanvas = piddlePIL.PILCanvas() else: tcanvas = canvas normal = piddle.Font(face=_defaultfont) bold = piddle.Font(face=_defaultfont, bold=1) def pickfont(st): if st[0] == '*': return (bold, '%s' % st[1:]) else: return (normal, '%s' % st) # compute the height lineskip = int(line_size * tcanvas.fontHeight(normal) + 1) labellen = [] for s in labels: (myfont, st) = pickfont(s) labellen.append(tcanvas.stringWidth(st, font=myfont)) maxlabel = max(labellen) width = height = int(1 + 2.0 * margin + hook + maxlabel + lineskip * (len(labels)) + tcanvas.fontHeight(normal)) if block == None: block = lineskip / 2 - 1 if canvas == None: canvas = piddlePIL.PILCanvas(size=(width, height)) _colorize = _color_picker(color_mode) ### DRAWING ### font = normal offset = maxlabel + margin halfline = canvas.fontAscent(normal) / 2.0 # print names for i in range(len(labels)): # self.order identifies the label at a particular row idx = self.order[i] - 1 x = offset - labellen[idx] y = offset + lineskip * (i + 1) # horizontal (myfont, xst) = pickfont(labels[idx]) if not diagonal or i > 0 or len(att_colors) > 0: canvas.drawString(xst, x, y + halfline, font=myfont) y2 = offset + lineskip * (i + 1) # vertical if diagonal: if len(att_colors) > 0: canvas.drawString(xst, y + block + halfline - lineskip + hook, y2 + block - hook - lineskip, angle=90, font=myfont) elif i < len(labels) - 1: canvas.drawString(xst, y + block + halfline - lineskip + hook, y2 + block - hook, angle=90, font=myfont) elif not diagonal: canvas.drawString(xst, y + block + halfline - lineskip + hook, offset + lineskip - block - hook, angle=90, font=myfont) for j in range(i): idx2 = self.order[j] - 1 colo = _colorize(diss[max(idx, idx2) - 1][min(idx, idx2)]) x = offset + hook + lineskip * (j) + block y = offset + lineskip * (i + 1) canvas.drawRect(x - block, y - block, x + block, y + block, edgeColor=colo, fillColor=colo) if not diagonal: x = offset + hook + lineskip * (i) + block y = offset + lineskip * (j + 1) canvas.drawRect(x - block, y - block, x + block, y + block, edgeColor=colo, fillColor=colo) if len(att_colors) > 0: # render the gain x = offset + hook + lineskip * (i) + block y = offset + lineskip * (i + 1) colo = _colorize(att_colors[idx]) canvas.drawRect(x - block, y - block, x + block, y + block, edgeColor=colo, fillColor=colo) canvas.flush() return canvas