def getElements(self, node_id, x, y, x_label=None, y_label=None): e = NodeDecorator.getElements(self, node_id, x, y) if x_label is None: x_label = x if y_label is None: y_label = y t = self.mTree.node(node_id).data.taxon species = self.mExtractSpecies(t) if species not in self.mMapSpecies2Colour: self.mMapSpecies2Colour[species] = COLOURS[len( self.mMapSpecies2Colour) % len(COLOURS)] if species in self.mMapSpecies2Name: tx = re.sub(species, "%s" % self.mMapSpecies2Name[species], t) else: tx = t colour = self.getColour(node_id, x, y) if self.mPlotLabel: ee = SVGdraw.text(x_label, y_label, tx, self.mFontSize, self.mFont, stroke="rgb(%i,%i,%i)" % colour, text_anchor="left") if self.mMapTaxon2URL is not None: url = self.mMapTaxon2URL(t) if url: l = SVGdraw.link(url) l.addElement(ee) e.append(l) else: e.append(ee) else: e.append(ee) return e
def getElements(self, node_id, x, y, x_label=None, y_label=None): e = NodeDecorator.getElements(self, node_id, x, y) if x_label is None: x_label = x if y_label is None: y_label = y t = self.mTree.node(node_id).data.taxon species = self.mExtractSpecies(t) if species not in self.mMapSpecies2Colour: self.mMapSpecies2Colour[species] = COLOURS[ len(self.mMapSpecies2Colour) % len(COLOURS)] if species in self.mMapSpecies2Name: tx = re.sub(species, "%s" % self.mMapSpecies2Name[species], t) else: tx = t colour = self.getColour(node_id, x, y) if self.mPlotLabel: ee = SVGdraw.text(x_label, y_label, tx, self.mFontSize, self.mFont, stroke="rgb(%i,%i,%i)" % colour, text_anchor="left") if self.mMapTaxon2URL is not None: url = self.mMapTaxon2URL(t) if url: l = SVGdraw.link(url) l.addElement(ee) e.append(l) else: e.append(ee) else: e.append(ee) return e
def addDuplication(self, entries, map_gene2pos, height, url=None, with_separator=True, link_to_previous=False, quality2symbol={}, quality2mask={}): """add a dot in row/col.""" mi, ma = None, 0 pos = bisect.bisect(self.mColourThresholds, height) master_colour = self.mColours[pos] chrs = {} points = [] if not link_to_previous: self.mPreviousPoints = {} ######################################################## ######################################################## ######################################################## # convert gene list to a set of points ######################################################## for species, transcript, gene, quality in entries: chr, strand, first_res, last_res = map_gene2pos[gene] chrs[chr] = 1 pos1 = self.getPosition(chr, strand, first_res) pos2 = self.getPosition(chr, strand, last_res) a = min(pos1, pos2) b = max(pos1, pos2) if mi is None: mi = a else: mi = min(a, mi) ma = max(b, ma) points.append((pos1, pos2, gene, quality, chr)) ######################################################## ######################################################## ######################################################## # decide whether we need to increment the radius ######################################################## cis = len(chrs) == 1 old_radius = self.mRadius is_overlap = False if cis: if not self.mLastChr: self.mLastChr = chr if chr != self.mLastChr: self.mRadius = self.mRadiusFallBack self.mLastMax = ma self.mPreviousMax = ma self.mLastChr = chr else: if self.mPreviousMax + self.mMinDistance > mi: # overlap due to close proximitiy self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() # true overlap if self.mPreviousMax > mi: is_overlap = True elif self.mLastMax + self.mMinDistance > mi: pass else: self.mRadius = self.mRadiusFallBack self.mLastMax = max(self.mLastMax, ma) else: if self.mLastMax > mi: self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() self.mPreviousMin = mi self.mPreviousMax = ma self.mPreviousCis = cis self.mRadiusMax = max(self.mRadius, self.mRadiusMax) ######################################################## ######################################################## ######################################################## # draw points ######################################################## link_colour = master_colour link_rad_width = self.mLinkRadStrokeWidth link_arc_width = self.mLinkArcStrokeWidth new_points = {} for pos1, pos2, gene, quality, chr in points: angle = self.getAngle((pos1 + pos2) / 2) x, y = self.getPosOnArc(angle, self.mRadius) try: symbol = quality2symbol[quality] except KeyError: symbol = "rect" if quality in quality2mask: colour = self.mLinkColourSymbolMasked link_colour = self.mLinkColourMasked link_rad_width = self.mLinkStrokeWidthMasked link_arc_width = self.mLinkStrokeWidthMasked else: colour = master_colour if gene in self.mPreviousPoints: continue new_points[gene] = (x, y, angle, quality, chr) if symbol == "circle": ee = SVGdraw.circle(x, y, self.mLinkSymbolSize, fill="rgb(%i,%i,%i)" % colour, stroke="black", stroke_width=self.mLinkStrokeWidthSymbol) elif symbol == "rect": ee = SVGdraw.rect(x - self.mLinkSymbolSize / 2, y - self.mLinkSymbolSize / 2, self.mLinkSymbolSize, self.mLinkSymbolSize, fill="rgb(%i,%i,%i)" % colour, stroke="black", stroke_width=self.mLinkStrokeWidthSymbol) if url: e = SVGdraw.link(url % gene) e.addElement(ee) else: e = ee self.addWheelElement(e) ######################################################## ######################################################## ######################################################## # write all arcs in between old points and new points # cis: circular arc # trans: radial arc ######################################################## angles = [] for x1, y1, angle1, quality1, chr1 in new_points.values(): # reduce clutter by not writing arc to the same angle for x2, y2, angle2, quality2, chr2 in self.mPreviousPoints.values(): for a in angles: if a - self.mAngleResolution < angle2 < a + self.mAngleResolution: break else: angles.append(angle2) d = SVGdraw.pathdata(x1, y1) if chr1 == chr2: d.relellarc( self.mRadius, self.mRadius, 0, 0, 1, x2 - x1, y2 - y1) link_width = link_rad_width else: d.relellarc( self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2 - x1, y2 - y1) link_width = link_arc_width e = SVGdraw.path(d, fill="none", stroke="rgb(%i,%i,%i)" % link_colour, stroke_width=link_width) self.addWheelElement(e, self.mPlaneLinks) # plot lines between new points new_genes = new_points.keys() for g1 in range(len(new_genes) - 1): x1, y1, angle1, quality1, chr1 = new_points[new_genes[g1]] for g2 in range(g1 + 1, len(new_genes)): x2, y2, angle2, quality2, chr2 = new_points[new_genes[g2]] for a in angles: if a - self.mAngleResolution < angle2 < a + self.mAngleResolution: break else: angles.append(angle2) d = SVGdraw.pathdata(x1, y1) if chr1 == chr2: d.relellarc( self.mRadius, self.mRadius, 0, 0, 1, x2 - x1, y2 - y1) link_width = link_rad_width else: d.relellarc( self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2 - x1, y2 - y1) link_width = link_arc_width e = SVGdraw.path(d, fill="none", stroke="rgb(%i,%i,%i)" % link_colour, stroke_width=link_width) self.addWheelElement(e, self.mPlaneLinks) # add new points to old points for k, v in new_points.items(): self.mPreviousPoints[k] = v
def addDuplication(self, entries, map_gene2pos, height, url=None, with_separator=True, link_to_previous=False, quality2symbol={}, quality2mask={}): """add a dot in row/col.""" mi, ma = None, 0 pos = bisect.bisect(self.mColourThresholds, height) master_colour = self.mColours[pos] chrs = {} points = [] for species, transcript, gene, quality in entries: chr, strand, first_res, last_res = map_gene2pos[gene] chrs[chr] = 1 pos1 = self.getPosition(chr, strand, first_res) pos2 = self.getPosition(chr, strand, last_res) a = min(pos1, pos2) b = max(pos1, pos2) if mi is None: mi = a else: mi = min(a, mi) ma = max(b, ma) points.append((pos1, pos2, gene, quality)) # decide whether we need to increment the radius cis = len(chrs) == 1 old_radius = self.mRadius is_overlap = False if cis: if not self.mLastChr: self.mLastChr = chr if chr != self.mLastChr: self.mRadius = self.mRadiusFallBack self.mLastMax = ma self.mPreviousMax = ma self.mLastChr = chr else: if self.mPreviousMax + self.mMinDistance > mi: # overlap due to close proximitiy self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() # true overlap if self.mPreviousMax > mi: is_overlap = True elif self.mLastMax + self.mMinDistance > mi: pass else: self.mRadius = self.mRadiusFallBack self.mLastMax = max(self.mLastMax, ma) else: if self.mLastMax > mi: self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() if cis and self.mPreviousCis and (link_to_previous or is_overlap): # print old_x1, old_y1, old_x2, old_y2, new_x1, new_y2, new_x2, # new_y2 r1 = old_radius r2 = self.mRadius old_x1, old_y1 = self.getPosOnArcForRadius(self.mPreviousMin, r1) old_x2, old_y2 = self.getPosOnArcForRadius(self.mPreviousMax, r1) new_x1, new_y1 = self.getPosOnArcForRadius(mi, r2) new_x2, new_y2 = self.getPosOnArcForRadius(ma, r2) if link_to_previous: # print cis, entries, chrs d = SVGdraw.pathdata(old_x1, old_y1) d.ellarc(r1, r1, 0, 0, 1, old_x2, old_y2) d.line(new_x2, new_y2) d.ellarc(r2, r2, 0, 0, 1, new_x1, new_y1) d.line(old_x1, old_y1) e = SVGdraw.path(d, fill="rgb(%i,%i,%i)" % GREY, stroke="rgb(%i,%i,%i)" % GREY, stroke_width=1) else: # get points of center old_x1, old_y1 = self.getPosOnArcForRadius( (self.mPreviousMax + self.mPreviousMin) / 2, r1) new_x1, new_y1 = self.getPosOnArcForRadius((ma + mi) / 2, r2) # lines for interleaved spans: skip if not ((self.mPreviousMin < mi and self.mPreviousMax > ma) or (self.mPreviousMin > mi and self.mPreviousMax < ma)): ## d = SVGdraw.pathdata( old_x2, old_y2 ) ## d.line( new_x2, new_y2 ) ## d.move( new_x1, new_y1 ) ## d.line( old_x1, old_y1 ) ## d.move( old_x2, old_y2 ) # e = SVGdraw.path( d, ## fill = "none", ## stroke = "rgb(%i,%i,%i)" % BLACK, # stroke_width = self.mMarkerWidth / 2 ) e = SVGdraw.line(old_x1, old_y1, new_x1, new_y1, fill="none", stroke="rgb(%i,%i,%i)" % GREY, stroke_width=self.mMarkerWidth / 2) else: # lines for covering spans, as these overlaps e = None # e = SVGdraw.line( old_x1, old_y1, ## new_x1, new_y1, ## fill = "none", ## stroke = "rgb(%i,%i,%i)" % GREY, # stroke_width = self.mMarkerWidth / 2 ) if e: self.addElement(e, self.mPlaneJoins) self.mPreviousMin = mi self.mPreviousMax = ma self.mPreviousCis = cis self.mRadiusMax = max(self.mRadius, self.mRadiusMax) # draw points link_colour = master_colour link_width = 10 for pos1, pos2, gene, quality in points: angle = self.getAngle((pos1 + pos2) / 2) x, y = self.getPosOnArc(angle, self.mRadius) try: symbol = quality2symbol[quality] except KeyError: symbol = "rect" if quality in quality2mask: colour = GREY link_colour = GREY link_width = 1 else: colour = master_colour if symbol == "circle": ee = SVGdraw.circle(x, y, self.mMarkerWidth, fill="rgb(%i,%i,%i)" % colour, stroke="black", stroke_width=1) elif symbol == "rect": ee = SVGdraw.rect(x - self.mMarkerWidth / 2, y - self.mMarkerWidth / 2, self.mMarkerWidth, self.mMarkerWidth, fill="rgb(%i,%i,%i)" % colour, stroke="black", stroke_width=1) if url: e = SVGdraw.link(url % gene) e.addElement(ee) else: e = ee self.addElement(e) angle1 = self.getAngle(mi) angle2 = self.getAngle(ma) x1, y1 = self.getPosOnArc(angle1, self.mRadius) x2, y2 = self.getPosOnArc(angle2, self.mRadius) d = SVGdraw.pathdata(x1, y1) if cis: d.ellarc(self.mRadius, self.mRadius, 0, 0, 1, x2, y2) else: d.ellarc(self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2, y2) e = SVGdraw.path(d, fill="none", stroke="rgb(%i,%i,%i)" % link_colour, stroke_width=link_width) self.addElement(e)
def plotGenes(self): """plot orthologs orthologwise.""" # sort all entries by coordinates # and build coordinates map_gene2coord = {} y = self.mHeaderHeight self.mMapGene2Coord = {} reference_genes = None for species in self.mSpeciesList: genes = self.getGenes(species) genes.sort(lambda x, y: cmp((x.contig, x.mFrom), (y.contig, y.mFrom))) if reference_genes: genes = self.getSortedGenes(genes, reference_genes) else: genes = self.getSortedGenesByBlockSize(genes) x = self.getRowWidth(genes) x = self.mHeaderWidth + (self.mDataWidth - x) / 2 last_contig, last_end = None, 0 # build list of genes to skip (note: this can be improved # by working in blocks from the start.) blocks = self.getBlocks(genes) for block in blocks: nlinks = 0 for gene in block: nlinks += len(self.mMapGroup2Genes[gene.mOrthologId]) if nlinks == len(block): continue x = self.addGroupStart(x, y, gene.contig, gene.mFrom) # count number of links to be made for gene in block: self.mMapGene2Coord[gene] = (x, y) ee = self.plotGene(x, y, gene) if self.mGeneUrl: e = SVGdraw.link(self.mGeneUrl % gene) e.addElement(ee) else: e = ee self.addElement(e) x += self.mBlockSize + self.mVerticalSeparator last_contig, last_end = gene.contig, gene.mTo y += self.mBlockSize + self.mHorizontalSeparator # set orientation if self.mOrientation == "local": reference_genes = genes elif self.mOrientation == "first": if not reference_genes: reference_genes = genes
def plotGenes(self): """plot orthologs orthologwise.""" ## sort all entries by coordinates ## and build coordinates map_gene2coord = {} y = self.mHeaderHeight self.mMapGene2Coord = {} reference_genes = None for species in self.mSpeciesList: genes = self.getGenes(species) genes.sort(lambda x, y: cmp((x.contig, x.mFrom), (y.contig, y.mFrom))) if reference_genes: genes = self.getSortedGenes(genes, reference_genes) else: genes = self.getSortedGenesByBlockSize(genes) x = self.getRowWidth(genes) x = self.mHeaderWidth + (self.mDataWidth - x) / 2 last_contig, last_end = None, 0 # build list of genes to skip (note: this can be improved # by working in blocks from the start.) blocks = self.getBlocks(genes) for block in blocks: nlinks = 0 for gene in block: nlinks += len(self.mMapGroup2Genes[gene.mOrthologId]) if nlinks == len(block): continue x = self.addGroupStart(x, y, gene.contig, gene.mFrom) # count number of links to be made for gene in block: self.mMapGene2Coord[gene] = (x, y) ee = self.plotGene(x, y, gene) if self.mGeneUrl: e = SVGdraw.link(self.mGeneUrl % gene) e.addElement(ee) else: e = ee self.addElement(e) x += self.mBlockSize + self.mVerticalSeparator last_contig, last_end = gene.contig, gene.mTo y += self.mBlockSize + self.mHorizontalSeparator ## set orientation if self.mOrientation == "local": reference_genes = genes elif self.mOrientation == "first": if not reference_genes: reference_genes = genes
def addDuplication( self, entries, map_gene2pos, height, url = None, with_separator=True, link_to_previous = False, quality2symbol = {}, quality2mask = {}): """add a dot in row/col.""" mi, ma = None, 0 pos = bisect.bisect( self.mColourThresholds, height ) master_colour = self.mColours[pos] chrs = {} points = [] for species, transcript, gene, quality in entries: chr, strand, first_res, last_res = map_gene2pos[gene] chrs[chr] = 1 pos1 = self.getPosition( chr, strand, first_res ) pos2 = self.getPosition( chr, strand, last_res ) a = min( pos1, pos2 ) b = max( pos1, pos2 ) if mi == None: mi = a else: mi = min(a, mi) ma = max(b, ma) points.append( (pos1, pos2, gene, quality) ) ## decide whether we need to increment the radius cis = len(chrs) == 1 old_radius = self.mRadius is_overlap = False if cis: if not self.mLastChr: self.mLastChr = chr if chr != self.mLastChr: self.mRadius = self.mRadiusFallBack self.mLastMax = ma self.mPreviousMax = ma self.mLastChr = chr else: if self.mPreviousMax + self.mMinDistance > mi: ## overlap due to close proximitiy self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() ## true overlap if self.mPreviousMax > mi: is_overlap = True elif self.mLastMax + self.mMinDistance > mi: pass else: self.mRadius = self.mRadiusFallBack self.mLastMax = max(self.mLastMax, ma) else: if self.mLastMax > mi: self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() if cis and self.mPreviousCis and (link_to_previous or is_overlap): # print old_x1, old_y1, old_x2, old_y2, new_x1, new_y2, new_x2, new_y2 r1 = old_radius r2 = self.mRadius old_x1, old_y1 = self.getPosOnArcForRadius( self.mPreviousMin, r1 ) old_x2, old_y2 = self.getPosOnArcForRadius( self.mPreviousMax, r1 ) new_x1, new_y1 = self.getPosOnArcForRadius( mi, r2 ) new_x2, new_y2 = self.getPosOnArcForRadius( ma, r2 ) if link_to_previous: # print cis, entries, chrs d = SVGdraw.pathdata( old_x1, old_y1 ) d.ellarc( r1, r1, 0, 0, 1, old_x2, old_y2 ) d.line( new_x2, new_y2 ) d.ellarc( r2, r2, 0, 0, 1, new_x1, new_y1 ) d.line( old_x1, old_y1 ) e = SVGdraw.path( d, fill = "rgb(%i,%i,%i)" % GREY, stroke = "rgb(%i,%i,%i)" % GREY, stroke_width = 1 ) else: # get points of center old_x1, old_y1 = self.getPosOnArcForRadius( (self.mPreviousMax + self.mPreviousMin) / 2, r1 ) new_x1, new_y1 = self.getPosOnArcForRadius( (ma + mi) / 2, r2 ) # lines for interleaved spans: skip if not ((self.mPreviousMin < mi and self.mPreviousMax > ma) or \ (self.mPreviousMin > mi and self.mPreviousMax < ma)) : ## d = SVGdraw.pathdata( old_x2, old_y2 ) ## d.line( new_x2, new_y2 ) ## d.move( new_x1, new_y1 ) ## d.line( old_x1, old_y1 ) ## d.move( old_x2, old_y2 ) ## e = SVGdraw.path( d, ## fill = "none", ## stroke = "rgb(%i,%i,%i)" % BLACK, ## stroke_width = self.mMarkerWidth / 2 ) e = SVGdraw.line( old_x1, old_y1, new_x1, new_y1, fill = "none", stroke = "rgb(%i,%i,%i)" % GREY, stroke_width = self.mMarkerWidth / 2 ) else: # lines for covering spans, as these overlaps e = None ## e = SVGdraw.line( old_x1, old_y1, ## new_x1, new_y1, ## fill = "none", ## stroke = "rgb(%i,%i,%i)" % GREY, ## stroke_width = self.mMarkerWidth / 2 ) if e: self.addElement( e, self.mPlaneJoins ) self.mPreviousMin = mi self.mPreviousMax = ma self.mPreviousCis = cis self.mRadiusMax = max(self.mRadius, self.mRadiusMax) ## draw points link_colour = master_colour link_width = 10 for pos1, pos2, gene, quality in points: angle = self.getAngle( (pos1 + pos2) / 2 ) x,y = self.getPosOnArc( angle, self.mRadius ) try: symbol = quality2symbol[quality] except KeyError: symbol = "rect" if quality in quality2mask: colour = GREY link_colour = GREY link_width = 1 else: colour = master_colour if symbol == "circle": ee = SVGdraw.circle( x, y, self.mMarkerWidth, fill = "rgb(%i,%i,%i)" % colour, stroke="black", stroke_width= 1) elif symbol == "rect": ee = SVGdraw.rect( x-self.mMarkerWidth/2, y-self.mMarkerWidth/2, self.mMarkerWidth, self.mMarkerWidth, fill = "rgb(%i,%i,%i)" % colour, stroke="black", stroke_width= 1) if url: e = SVGdraw.link( url % gene ) e.addElement( ee ) else: e = ee self.addElement( e ) angle1 = self.getAngle( mi ) angle2 = self.getAngle( ma ) x1,y1 = self.getPosOnArc( angle1, self.mRadius ) x2,y2 = self.getPosOnArc( angle2, self.mRadius ) d = SVGdraw.pathdata( x1, y1 ) if cis: d.ellarc( self.mRadius, self.mRadius, 0, 0, 1, x2, y2 ) else: d.ellarc( self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2, y2 ) e = SVGdraw.path( d, fill = "none", stroke = "rgb(%i,%i,%i)" % link_colour, stroke_width = link_width ) self.addElement(e)