def excision(args): """ %prog excision Illustrate the mechanism of illegitimate recombination. """ p = OptionParser(__doc__) opts, args = p.parse_args(args) fig = plt.figure(1, (5, 5)) root = fig.add_axes([0, 0, 1, 1]) plt.plot((0.2, 0.8), (0.6, 0.6), "r-", lw=3) plt.plot((0.4, 0.6), (0.6, 0.6), "b>-", mfc="g", mec="w", ms=12, lw=3) plt.plot((0.3, 0.7), (0.5, 0.5), "r-", lw=3) plt.plot((0.5, ), (0.5, ), "b>-", mfc="g", mec="w", ms=12, lw=3) # Circle excision plt.plot((0.5, ), (0.45, ), "b>-", mfc="g", mec="w", ms=12, lw=3) circle = CirclePolygon((0.5, 0.4), 0.05, fill=False, lw=3, ec="b") root.add_patch(circle) arrow_dist = 0.07 ar_xpos, ar_ypos = 0.5, 0.52 root.annotate(" ", (ar_xpos, ar_ypos), (ar_xpos, ar_ypos + arrow_dist), arrowprops=arrowprops) RoundLabel(root, 0.2, 0.64, "Gene") RoundLabel(root, 0.3, 0.54, "Excision") root.set_xlim(0, 1) root.set_ylim(0, 1) root.set_axis_off() figname = fname() + ".pdf" savefig(figname, dpi=300)
def __init__( self, fig, root, datafile, bedfile, layoutfile, switch=None, tree=None, extra_features=None, chr_label=True, loc_label=True, genelabelsize=0, pad=0.05, vpad=0.015, scalebar=False, shadestyle="curve", glyphstyle="arrow", glyphcolor: BasePalette = OrientationPalette(), ): _, h = fig.get_figwidth(), fig.get_figheight() bed = Bed(bedfile) order = bed.order bf = BlockFile(datafile) self.layout = lo = Layout(layoutfile) switch = DictFile(switch, delimiter="\t") if switch else None if extra_features: extra_features = Bed(extra_features) exts = [] extras = [] for i in range(bf.ncols): ext = bf.get_extent(i, order) exts.append(ext) if extra_features: start, end, si, ei, chr, orientation, span = ext start, end = start.start, end.end # start, end coordinates ef = list(extra_features.extract(chr, start, end)) # Pruning removes minor features with < 0.1% of the region ef_pruned = [x for x in ef if x.span >= span / 1000] print( "Extracted {0} features " "({1} after pruning)".format(len(ef), len(ef_pruned)), file=sys.stderr, ) extras.append(ef_pruned) maxspan = max(exts, key=lambda x: x[-1])[-1] scale = maxspan / 0.65 self.gg = gg = {} self.rr = [] ymids = [] glyphcolor = ( OrientationPalette() if glyphcolor == "orientation" else OrthoGroupPalette(bf.grouper()) ) for i in range(bf.ncols): ext = exts[i] ef = extras[i] if extras else None r = Region( root, ext, lo[i], bed, scale, switch, genelabelsize=genelabelsize, chr_label=chr_label, loc_label=loc_label, vpad=vpad, extra_features=ef, glyphstyle=glyphstyle, glyphcolor=glyphcolor, ) self.rr.append(r) # Use tid and accn to store gene positions gg.update(dict(((i, k), v) for k, v in r.gg.items())) ymids.append(r.y) def offset(samearc): if samearc == "above": return 2 * pad if samearc == "above2": return 4 * pad if samearc == "below": return -2 * pad if samearc == "below2": return -4 * pad for i, j, blockcolor, samearc in lo.edges: for ga, gb, h in bf.iter_pairs(i, j): a, b = gg[(i, ga)], gg[(j, gb)] if samearc is not None: ymid = ymids[i] + offset(samearc) else: ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, fc=blockcolor, lw=0, alpha=1, style=shadestyle) for ga, gb, h in bf.iter_pairs(i, j, highlight=True): a, b = gg[(i, ga)], gg[(j, gb)] if samearc is not None: ymid = ymids[i] + offset(samearc) else: ymid = (ymids[i] + ymids[j]) / 2 Shade( root, a, b, ymid, alpha=1, highlight=h, zorder=2, style=shadestyle ) if scalebar: print("Build scalebar (scale={})".format(scale), file=sys.stderr) # Find the best length of the scalebar ar = [1, 2, 5] candidates = ( [1000 * x for x in ar] + [10000 * x for x in ar] + [100000 * x for x in ar] ) # Find the one that's close to an optimal canvas size dists = [(abs(x / scale - 0.12), x) for x in candidates] dist, candidate = min(dists) dist = candidate / scale x, y, yp = 0.22, 0.92, 0.005 a, b = x - dist / 2, x + dist / 2 lsg = "lightslategrey" root.plot([a, a], [y - yp, y + yp], "-", lw=2, color=lsg) root.plot([b, b], [y - yp, y + yp], "-", lw=2, color=lsg) root.plot([a, b], [y, y], "-", lw=2, color=lsg) root.text( x, y + 0.02, human_size(candidate, precision=0), ha="center", va="center", ) if tree: from jcvi.graphics.tree import draw_tree, read_trees trees = read_trees(tree) ntrees = len(trees) logging.debug("A total of {0} trees imported.".format(ntrees)) xiv = 1.0 / ntrees yiv = 0.3 xstart = 0 ystart = min(ymids) - 0.4 for i in range(ntrees): ax = fig.add_axes([xstart, ystart, xiv, yiv]) label, outgroup, color, tx = trees[i] draw_tree( ax, tx, outgroup=outgroup, rmargin=0.4, leaffont=11, treecolor=color, supportcolor=color, leafcolor=color, ) xstart += xiv RoundLabel(ax, 0.5, 0.3, label, fill=True, fc="lavender", color=color)
def __init__(self, fig, root, datafile, bedfile, layoutfile, switch=None, tree=None, extra_features=None, chr_label=True, loc_label=True, pad=.04): w, h = fig.get_figwidth(), fig.get_figheight() bed = Bed(bedfile) order = bed.order bf = BlockFile(datafile) self.layout = lo = Layout(layoutfile) switch = DictFile(switch, delimiter="\t") if switch else None if extra_features: extra_features = Bed(extra_features) exts = [] extras = [] for i in xrange(bf.ncols): ext = bf.get_extent(i, order) exts.append(ext) if extra_features: start, end, si, ei, chr, orientation, span = ext start, end = start.start, end.end # start, end coordinates ef = list(extra_features.extract(chr, start, end)) # Pruning removes minor features with < 0.1% of the region ef_pruned = [x for x in ef if x.span >= span / 1000] print >> sys.stderr, "Extracted {0} features "\ "({1} after pruning)".format(len(ef), len(ef_pruned)) extras.append(ef_pruned) maxspan = max(exts, key=lambda x: x[-1])[-1] scale = maxspan / .65 self.gg = gg = {} self.rr = [] ymids = [] vpad = .012 * w / h for i in xrange(bf.ncols): ext = exts[i] ef = extras[i] if extras else None r = Region(root, ext, lo[i], bed, scale, switch, chr_label=chr_label, loc_label=loc_label, vpad=vpad, extra_features=ef) self.rr.append(r) # Use tid and accn to store gene positions gg.update(dict(((i, k), v) for k, v in r.gg.items())) ymids.append(r.y) for i, j in lo.edges: for ga, gb, h in bf.iter_pairs(i, j): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, fc="gainsboro", lw=0, alpha=1) for ga, gb, h in bf.iter_pairs(i, j, highlight=True): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, alpha=1, highlight=h, zorder=2) if tree: from jcvi.graphics.tree import draw_tree, read_trees trees = read_trees(tree) ntrees = len(trees) logging.debug("A total of {0} trees imported.".format(ntrees)) xiv = 1. / ntrees yiv = .3 xstart = 0 ystart = min(ymids) - .4 for i in xrange(ntrees): ax = fig.add_axes([xstart, ystart, xiv, yiv]) label, outgroup, tx = trees[i] draw_tree(ax, tx, outgroup=outgroup, rmargin=.4, leaffont=11) xstart += xiv RoundLabel(ax, .5, .3, label, fill=True, fc="lavender", color="r")
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)
def __init__(self, fig, root, datafile, bedfile, layoutfile, switch=None, tree=None, extra_features=None, chr_label=True, loc_label=True, pad=.04, scalebar=False): w, h = fig.get_figwidth(), fig.get_figheight() bed = Bed(bedfile) order = bed.order bf = BlockFile(datafile) self.layout = lo = Layout(layoutfile) switch = DictFile(switch, delimiter="\t") if switch else None if extra_features: extra_features = Bed(extra_features) exts = [] extras = [] for i in xrange(bf.ncols): ext = bf.get_extent(i, order) exts.append(ext) if extra_features: start, end, si, ei, chr, orientation, span = ext start, end = start.start, end.end # start, end coordinates ef = list(extra_features.extract(chr, start, end)) # Pruning removes minor features with < 0.1% of the region ef_pruned = [x for x in ef if x.span >= span / 1000] print >> sys.stderr, "Extracted {0} features "\ "({1} after pruning)".format(len(ef), len(ef_pruned)) extras.append(ef_pruned) maxspan = max(exts, key=lambda x: x[-1])[-1] scale = maxspan / .65 self.gg = gg = {} self.rr = [] ymids = [] vpad = .012 * w / h for i in xrange(bf.ncols): ext = exts[i] ef = extras[i] if extras else None r = Region(root, ext, lo[i], bed, scale, switch, chr_label=chr_label, loc_label=loc_label, vpad=vpad, extra_features=ef) self.rr.append(r) # Use tid and accn to store gene positions gg.update(dict(((i, k), v) for k, v in r.gg.items())) ymids.append(r.y) for i, j in lo.edges: for ga, gb, h in bf.iter_pairs(i, j): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, fc="gainsboro", lw=0, alpha=1) for ga, gb, h in bf.iter_pairs(i, j, highlight=True): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, alpha=1, highlight=h, zorder=2) if scalebar: print >> sys.stderr, "Build scalebar (scale={})".format(scale) # Find the best length of the scalebar ar = [1, 2, 5] candidates = [1000 * x for x in ar] + [10000 * x for x in ar] + \ [100000 * x for x in ar] # Find the one that's close to an optimal canvas size dists = [(abs(x / scale - .12), x) for x in candidates] dist, candidate = min(dists) dist = candidate / scale x, y, yp = .2, .96, .005 a, b = x - dist / 2, x + dist / 2 lsg = "lightslategrey" root.plot([a, a], [y - yp, y + yp], "-", lw=2, color=lsg) root.plot([b, b], [y - yp, y + yp], "-", lw=2, color=lsg) root.plot([a, b], [y, y], "-", lw=2, color=lsg) root.text(x, y + .02, human_size(candidate, precision=0), ha="center", va="center") if tree: from jcvi.graphics.tree import draw_tree, read_trees trees = read_trees(tree) ntrees = len(trees) logging.debug("A total of {0} trees imported.".format(ntrees)) xiv = 1. / ntrees yiv = .3 xstart = 0 ystart = min(ymids) - .4 for i in xrange(ntrees): ax = fig.add_axes([xstart, ystart, xiv, yiv]) label, outgroup, tx = trees[i] draw_tree(ax, tx, outgroup=outgroup, rmargin=.4, leaffont=11) xstart += xiv RoundLabel(ax, .5, .3, label, fill=True, fc="lavender", color="r")
def __init__(self, fig, root, datafile, bedfile, layoutfile, switch=None, tree=None, chr_label=True, pad=.04): w, h = fig.get_figwidth(), fig.get_figheight() bed = Bed(bedfile) order = bed.order bf = BlockFile(datafile) lo = Layout(layoutfile) switch = DictFile(switch, delimiter="\t") if switch else None exts = [] for i in xrange(bf.ncols): ext = bf.get_extent(i, order) exts.append(ext) maxspan = max(exts, key=lambda x: x[-1])[-1] scale = maxspan / .65 self.gg = gg = {} self.rr = [] ymids = [] vpad = .012 * w / h for i in xrange(bf.ncols): ext = exts[i] r = Region(root, ext, lo[i], bed, scale, switch, chr_label=chr_label, vpad=vpad) self.rr.append(r) # Use tid and accn to store gene positions gg.update(dict(((i, k), v) for k, v in r.gg.items())) ymids.append(r.y) for i, j in lo.edges: for ga, gb, h in bf.iter_pairs(i, j): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, fc="gainsboro", lw=0, alpha=1) for ga, gb, h in bf.iter_pairs(i, j, highlight=True): a, b = gg[(i, ga)], gg[(j, gb)] ymid = (ymids[i] + ymids[j]) / 2 Shade(root, a, b, ymid, alpha=1, highlight=h, zorder=2) if tree: from jcvi.graphics.tree import draw_tree, read_trees trees = read_trees(tree) ntrees = len(trees) logging.debug("A total of {0} trees imported.".format(ntrees)) xiv = 1. / ntrees yiv = .3 xstart = 0 ystart = min(ymids) - .4 for i in xrange(ntrees): ax = fig.add_axes([xstart, ystart, xiv, yiv]) label, outgroup, tx = trees[i] draw_tree(ax, tx, outgroup=outgroup, rmargin=.4) xstart += xiv RoundLabel(ax, .5, .3, label, fill=True, fc="lavender", color="r")