def __init__(self, ax, x, y1, y2, y3, width=.015, fc="k", fill=False, zorder=2): """ Chromosome with centromeres at y2 position """ pts = [] r = width * .5 pts += plot_cap((x, y1 - r), np.radians(range(180)), r) pts += [[x - r, y1 - r], [x - r, y2 + r]] pts += plot_cap((x, y2 + r), np.radians(range(180, 360)), r) pts += [[x + r, y2 + r], [x + r, y1 - r]] ax.add_patch(Polygon(pts, fc=fc, fill=fill, zorder=zorder)) pts = [] pts += plot_cap((x, y2 - r), np.radians(range(180)), r) pts += [[x - r, y2 - r], [x - r, y3 + r]] pts += plot_cap((x, y3 + r), np.radians(range(180, 360)), r) pts += [[x + r, y3 + r], [x + r, y2 - r]] ax.add_patch(Polygon(pts, fc=fc, fill=fill, zorder=zorder)) ax.add_patch( CirclePolygon((x, y2), radius=r * .5, fc="k", ec="k", zorder=zorder))
def __init__(self, ax, x1, x2, y, height, gradient=True, tip=.0025, \ color="k", **kwargs): super(GeneGlyph, self).__init__(ax) # Figure out the polygon vertices first orientation = 1 if x1 < x2 else -1 level = 10 # Frame p1 = (x1, y - height * .5) p2 = (x2 - orientation * tip, y - height * .5) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * .5) p5 = (x1, y + .5 * height) self.append(Polygon([p1, p2, p3, p4, p5], ec=color, **kwargs)) if gradient: zz = kwargs.get("zorder", 1) zz += 1 # Patch (apply white mask) for cascade in np.arange(0, .5, .5 / level): p1 = (x1, y - height * cascade) p2 = (x2 - orientation * tip, y - height * cascade) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * cascade) p5 = (x1, y + height * cascade) self.append(Polygon([p1, p2, p3, p4, p5], fc='w', \ lw=0, alpha=.2, zorder=zz)) self.add_patches()
def __init__(self, ax, x1, x2, y, height=.015, ec="k", patch=None, patchcolor='lightgrey', lw=1, fc=None, zorder=2, roundrect=False): """ Horizontal version of the Chromosome glyph above. """ x1, x2 = sorted((x1, x2)) super(HorizontalChromosome, self).__init__(ax) pts, r = self.get_pts(x1, x2, y, height) if roundrect: RoundRect(ax, (x1, y - height * .5), x2 - x1, height, fill=False, lw=lw, ec=ec, zorder=zorder + 1) else: self.append(Polygon(pts, fill=False, lw=lw, ec=ec, zorder=zorder)) if fc: pts, r = self.get_pts(x1, x2, y, height / 2) if roundrect: RoundRect(ax, (x1, y - height / 4), x2 - x1, height / 2, fc=fc, lw=0, zorder=zorder) else: self.append(Polygon(pts, fc=fc, lw=0, zorder=zorder)) if patch: rr = r * .9 # Shrink a bit for the patches for i in xrange(0, len(patch), 2): if i + 1 > len(patch) - 1: continue p1, p2 = patch[i], patch[i + 1] self.append(Rectangle((p1, y - rr), p2 - p1, 2 * rr, lw=0, fc=patchcolor)) self.add_patches()
def __init__(self, ax, x1, x2, y, height, gradient=True, tip=0.0025, color="k", shadow=False, **kwargs): super(GeneGlyph, self).__init__(ax) # Figure out the polygon vertices first orientation = 1 if x1 < x2 else -1 level = 10 tip = min(tip, abs(x1 - x2)) # Frame p1 = (x1, y - height * 0.5) p2 = (x2 - orientation * tip, y - height * 0.5) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * 0.5) p5 = (x1, y + 0.5 * height) if "fc" not in kwargs: kwargs["fc"] = color if "ec" not in kwargs: kwargs["ec"] = color P = Polygon([p1, p2, p3, p4, p5], **kwargs) self.append(P) if gradient: zz = kwargs.get("zorder", 1) zz += 1 # Patch (apply white mask) for cascade in np.arange(0, 0.5, 0.5 / level): p1 = (x1, y - height * cascade) p2 = (x2 - orientation * tip, y - height * cascade) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * cascade) p5 = (x1, y + height * cascade) self.append( Polygon([p1, p2, p3, p4, p5], fc="w", lw=0, alpha=0.2, zorder=zz)) if shadow: import matplotlib.patheffects as pe P.set_path_effects([pe.withSimplePatchShadow((1, -1), alpha=0.4)]) self.add_patches()
def __init__(self, ax, x, y1, y2, width=.015, ec="k", patch=None, lw=1, fc="k", zorder=2): """ Chromosome with positions given in (x, y1) => (x, y2) The chromosome can also be patched, e.g. to show scaffold composition in alternating shades. Use a list of starting locations to segment. """ y1, y2 = sorted((y1, y2)) super(Chromosome, self).__init__(ax) pts, r = self.get_pts(x, y1, y2, width) self.append(Polygon(pts, fill=False, lw=lw, ec=ec, zorder=zorder)) if patch: rr = r * .9 # Shrink a bit for the patches for i in xrange(0, len(patch), 2): if i + 1 > len(patch) - 1: continue p1, p2 = patch[i], patch[i + 1] self.append( Rectangle((x - rr, p1), 2 * rr, p2 - p1, lw=0, fc="lightgrey")) self.add_patches()
def __init__(self, ax, xy, width, height, shrink=.1, label=None, **kwargs): shrink *= height x, y = xy pts = [] # plot the four rounded cap one by one pts += plot_cap((x + width - shrink, y + height - shrink), np.radians(range(0, 90)), shrink) pts += [[x + width - shrink, y + height], [x + shrink, y + height]] pts += plot_cap((x + shrink, y + height - shrink), np.radians(range(90, 180)), shrink) pts += [[x, y + height - shrink], [x, y + shrink]] pts += plot_cap((x + shrink, y + shrink), np.radians(range(180, 270)), shrink) pts += [[x + shrink, y], [x + width - shrink, y]] pts += plot_cap((x + width - shrink, y + shrink), np.radians(range(270, 360)), shrink) pts += [[x + width, y + shrink], [x + width, y + height - shrink]] p1 = Polygon(pts, **kwargs) ax.add_patch(p1) # add a white transparency ellipse filter if label: ax.text(x + width / 2, y + height / 2, label, size=10, ha="center", va="center", color="w")
def draw_cytoband(ax, chrom, filename=datafile("hg38.band.txt"), ymid=0.5, width=0.99, height=0.11): import pandas as pd bands = pd.read_csv(filename, sep="\t") chrombands = bands[bands["#chrom"] == chrom] data = [] for i, (chr, start, end, name, gie) in chrombands.iterrows(): data.append((chr, start, end, name, gie)) chromsize = max(x[2] for x in data) scale = width * 1.0 / chromsize xstart, ystart = (1 - width) / 2, ymid - height / 2 bp_to_pos = lambda x: xstart + x * scale in_acen = False for chr, start, end, name, gie in data: color, alpha = get_color(gie) bplen = end - start if "acen" in gie: if in_acen: xys = [ (bp_to_pos(start), ymid), (bp_to_pos(end), ystart), (bp_to_pos(end), ystart + height), ] else: xys = [ (bp_to_pos(start), ystart), (bp_to_pos(start), ystart + height), (bp_to_pos(end), ymid), ] p = Polygon(xys, closed=True, ec="k", fc=color, alpha=alpha) in_acen = True else: p = Rectangle( (bp_to_pos(start), ystart), bplen * scale, height, ec="k", fc=color, alpha=alpha, ) # print bp_to_pos(end) ax.add_patch(p) ax.text( bp_to_pos((start + end) / 2), ymid + height * 0.8, name, rotation=40, color="lightslategray", ) ax.text(0.5, ystart - height, chrom, size=16, ha="center", va="center") ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.set_axis_off()
def plot_diagram(ax, x, y, label="S", title="syntenic", gradient=True): """ Part of the diagrams that are re-used. (x, y) marks the center of the diagram. Label determines the modification to the "S" graph. """ trackgap = 0.06 tracklen = 0.12 xa, xb = x - tracklen, x + tracklen ya, yb = y + trackgap, y - trackgap hsps = (((60, 150), (50, 130)), ((190, 225), (200, 240)), ((330, 280), (360, 310))) for yy in (ya, yb): ax.plot((xa, xb), (yy, yy), "-", color="gray", lw=2, zorder=1) ytip = 0.015 mrange = 400 m = lambda t: xa + t * 1.0 / mrange * tracklen * 2 for i, ((a, b), (c, d)) in enumerate(hsps): fb = False if label == "FB" and i == 1: c, d = 270, 280 fb = True if label == "G" and i == 0: c, d = 120, 65 a, b, c, d = [m(t) for t in (a, b, c, d)] color = "g" if i == 1 else "r" GeneGlyph(ax, a, b, ya, 2 * ytip, fc=color, gradient=gradient, zorder=10) if i == 1 and label in ("F", "G", "FN"): pass else: if fb: GeneGlyph( ax, c, d, yb, 2 * ytip, fc="w", tip=0, gradient=gradient, zorder=10 ) else: GeneGlyph(ax, c, d, yb, 2 * ytip, fc="r", gradient=gradient, zorder=10) r = Polygon( ((a, ya - ytip), (c, yb + ytip), (d, yb + ytip), (b, ya - ytip)), fc="r", alpha=0.2, ) if i == 1 and label not in ("S", "FB"): pass elif i == 0 and label == "G": pass else: ax.add_patch(r) if label == "FN": ax.text(x + 0.005, yb, "NNNNN", ha="center", size=7) title = "{0}: {1}".format(label, title) ax.text(x, ya + 5 * ytip, title, size=8, ha="center")
def __init__(self, ax, x1, x2, y, height, gradient=True, tip=.0025, \ color="k", shadow=False, **kwargs): super(GeneGlyph, self).__init__(ax) # Figure out the polygon vertices first orientation = 1 if x1 < x2 else -1 level = 10 tip = min(tip, abs(x1 - x2)) # Frame p1 = (x1, y - height * .5) p2 = (x2 - orientation * tip, y - height * .5) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * .5) p5 = (x1, y + .5*height) if "fc" not in kwargs: kwargs["fc"] = color if "ec" not in kwargs: kwargs["ec"] = color P = Polygon([p1, p2, p3, p4, p5], **kwargs) self.append(P) if gradient: zz = kwargs.get("zorder", 1) zz += 1 # Patch (apply white mask) for cascade in np.arange(0, .5, .5 / level): p1 = (x1, y - height * cascade) p2 = (x2 - orientation * tip, y - height * cascade) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * cascade) p5 = (x1, y + height * cascade) self.append(Polygon([p1, p2, p3, p4, p5], fc='w', \ lw=0, alpha=.2, zorder=zz)) if shadow: import matplotlib.patheffects as pe P.set_path_effects([pe.withSimplePatchShadow((1, -1), \ alpha=.4, patch_alpha=1)]) self.add_patches()
def __init__(self, ax, x1, x2, y, height, tip=.0025, **kwargs): # Figure out the polygon vertices first orientation = 1 if x1 < x2 else -1 level = 10 # Frame p1 = (x1, y - height * .5) p2 = (x2 - orientation * tip, y - height * .5) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * .5) p5 = (x1, y + .5 * height) ax.add_patch(Polygon([p1, p2, p3, p4, p5], ec='k', **kwargs)) zz = kwargs.get("zorder", 1) zz += 1 # Patch (apply white mask) for cascade in np.arange(0, .5, .5 / level): p1 = (x1, y - height * cascade) p2 = (x2 - orientation * tip, y - height * cascade) p3 = (x2, y) p4 = (x2 - orientation * tip, y + height * cascade) p5 = (x1, y + height * cascade) ax.add_patch(Polygon([p1, p2, p3, p4, p5], fc='w', \ lw=0, alpha=.2, zorder=zz))
def __init__(self, ax, x1, x2, y, height=.015, fc="k", fill=False, zorder=2): """ Chromosome with positions given in (x1, y) => (x2, y) """ pts = [] r = height * .5 pts += plot_cap((x1, y), np.radians(range(90, 270)), r) pts += [[x1, y - r], [x2, y - r]] pts += plot_cap((x2, y), np.radians(range(270, 450)), r) pts += [[x2, y + r], [x1, y + r]] ax.add_patch(Polygon(pts, fc=fc, fill=fill, zorder=zorder))
def __init__(self, ax, x, y1, y2, width=.015, fc="k", fill=False, zorder=2): """ Chromosome with positions given in (x, y1) => (x, y2) """ pts = [] r = width * .5 pts += plot_cap((x, y1 - r), np.radians(range(180)), r) pts += [[x - r, y1 - r], [x - r, y2 + r]] pts += plot_cap((x, y2 + r), np.radians(range(180, 360)), r) pts += [[x + r, y2 + r], [x + r, y1 - r]] ax.add_patch(Polygon(pts, fc=fc, fill=fill, zorder=zorder))
def bites(args): """ %prog bites Illustrate the pipeline for automated bite discovery. """ p = OptionParser(__doc__) opts, args = p.parse_args() fig = plt.figure(1, (6, 6)) root = fig.add_axes([0, 0, 1, 1]) # HSP pairs hsps = ( ((50, 150), (60, 180)), ((190, 250), (160, 235)), ((300, 360), (270, 330)), ((430, 470), (450, 490)), ((570, 620), (493, 543)), ((540, 555), (370, 385)), # non-collinear hsps ) titlepos = (0.9, 0.65, 0.4) titles = ("Compare orthologous region", "Find collinear HSPs", "Scan paired gaps") ytip = 0.01 mrange = 650.0 m = lambda x: x / mrange * 0.7 + 0.1 for i, (ya, title) in enumerate(zip(titlepos, titles)): yb = ya - 0.1 plt.plot((0.1, 0.8), (ya, ya), "-", color="gray", lw=2, zorder=1) plt.plot((0.1, 0.8), (yb, yb), "-", color="gray", lw=2, zorder=1) RoundLabel(root, 0.5, ya + 4 * ytip, title) root.text(0.9, ya, "A. thaliana", ha="center", va="center") root.text(0.9, yb, "B. rapa", ha="center", va="center") myhsps = hsps if i >= 1: myhsps = hsps[:-1] for (a, b), (c, d) in myhsps: a, b, c, d = [m(x) for x in (a, b, c, d)] r1 = Rectangle((a, ya - ytip), b - a, 2 * ytip, fc="r", lw=0, zorder=2) r2 = Rectangle((c, yb - ytip), d - c, 2 * ytip, fc="r", lw=0, zorder=2) r3 = Rectangle((a, ya - ytip), b - a, 2 * ytip, fill=False, zorder=3) r4 = Rectangle((c, yb - ytip), d - c, 2 * ytip, fill=False, zorder=3) r5 = Polygon( ((a, ya - ytip), (c, yb + ytip), (d, yb + ytip), (b, ya - ytip)), fc="r", alpha=0.2, ) rr = (r1, r2, r3, r4, r5) if i == 2: rr = rr[:-1] for r in rr: root.add_patch(r) # Gap pairs hspa, hspb = zip(*myhsps) gapa, gapb = [], [] for (a, b), (c, d) in pairwise(hspa): gapa.append((b + 1, c - 1)) for (a, b), (c, d) in pairwise(hspb): gapb.append((b + 1, c - 1)) gaps = zip(gapa, gapb) tpos = titlepos[-1] yy = tpos - 0.05 for i, ((a, b), (c, d)) in enumerate(gaps): i += 1 a, b, c, d = [m(x) for x in (a, b, c, d)] xx = (a + b + c + d) / 4 TextCircle(root, xx, yy, str(i)) # Bites ystart = 0.24 ytip = 0.05 bites = ( ("Bite(40=>-15)", True), ("Bite(50=>35)", False), ("Bite(70=>120)", False), ("Bite(100=>3)", True), ) for i, (bite, selected) in enumerate(bites): xx = 0.15 if (i % 2 == 0) else 0.55 yy = ystart - i / 2 * ytip i += 1 TextCircle(root, xx, yy, str(i)) color = "k" if selected else "gray" root.text(xx + ytip, yy, bite, size=10, color=color, va="center") root.set_xlim(0, 1) root.set_ylim(0, 1) root.set_axis_off() figname = fname() + ".pdf" savefig(figname, dpi=300)