class RulerTrack (Track):
    """Track for displaying a base-pair ruler along the genome"""

    def __init__(self, top=2.0, bottom=0.0, 
                 minicolor=color(.8,.8,.8), maincolor = color(0,0,0),
                 align=None,
                 text_align="middle",
                 text_color=color(0, 0, 0),
                 show=True,
                 fixed_height=True,
                 **options):
        
        Track.__init__(self, **options)
        self.top = top
        self.bottom = bottom
        self.minicolor = minicolor
        self.maincolor = maincolor
        self.text_align = text_align
        self.text_color = text_color
        self.show      = show
        self.shown     = show
        self.fixed_height = fixed_height
        
        if align != None:
            self.coords = alignlib.CoordConverter(align)
        else:
            self.coords = None
        
        self.multiscale = Multiscale(marginx=.5, marginy=.5,
                                     scalex=10, scaley=10)
       
    
    def draw(self):
        self.multiscale.init(self.get_window())

        self.start = self.view.start-1
        self.end = self.view.end
        self.height = self.top
        self.multiscale.reset()
        
        self.gid = group()
        return group(self.gid)
        
    
    def update(self):
        self.win = self.get_window()
        
        if not self.show:
            if self.shown:
                self.gid = self.win.replace_group(self.gid, group())
                self.shown = False
        else:
            self.shown = True
            
            if not self.multiscale.same_view():
                if self.coords == None:
                    g = self.draw_ruler(self.pos, 
                                       self.start, 
                                       self.end)
                else:
                    g = self.draw_align_ruler(self.pos, self.start, self.end)
                self.gid = self.win.replace_group(self.gid, g)
    
    
    def set_visible(self, visible):
        self.show = visible
    
    
    def draw_ruler(self, pos, start, end):
        worldx1, worldy1, worldx2, worldy2 = self.win.get_visible()
        screenwidth, screenheight = self.win.get_size()
        
        worldwidth = worldx2 - worldx1
        worldx1 -= worldwidth / 2.0
        worldx2 += worldwidth / 2.0

        # find appropriate unit if one is not given
        unit = visual.getRulerAutoSize(screenwidth, worldwidth)
        order = int(math.log10(unit))
        unit2, unitstr = visual.getUnitSuffix(unit)
        
        
        x, y = pos
        vis = []

        # make mini hashes
        if unit >= 10:
            vis.append(self.minicolor)
            i = unit * (max(start, worldx1 - x + start) // unit)
            while x + i - start <= worldx2 and i < end:
                if i >= start:
                    vis.append(lines(x + i - start, y+self.bottom, 
                                     x + i - start, y+self.top))
                i += unit // 10


        # make main hashes
        i = unit * (max(start, worldx1 - x + start) // unit)
        while x + i - start <= worldx2 and i < end:
            if i >= start:
                vis.append(self.maincolor)            
                vis.append(lines(x + i - start, y, x + i - start, y + self.top))
                vis.append(self.text_color)
                vis.append(text(str(int(i//unit2)) + unitstr, 
                                x + i - start, y, x + i -start - unit, y + self.top, 
                                self.text_align, "right"))
            i += unit

        # base line
        vis.append(lines(self.maincolor, x, y, x + end - start, y))

        return group(* vis)
    
    
    def draw_align_ruler(self, pos, start, end):
        worldx1, worldy1, worldx2, worldy2 = self.win.get_visible()
        screenwidth, screenheight = self.win.get_size()
        
        worldwidth = worldx2 - worldx1
        worldx1 -= worldwidth / 2.0
        worldx2 += worldwidth / 2.0

        # find appropriate unit if one is not given
        unit = visual.getRulerAutoSize(screenwidth, worldwidth)
        order = int(math.log10(unit))
        unit2, unitstr = visual.getUnitSuffix(unit)
        
        x, y = pos
        vis = []
        
        # make mini hashes
        vis.append(self.minicolor)
        i = unit * (max(start, worldx1 - x + start) // unit)
        while x + i - start <= worldx2 and i < end:
            if i >= start:
                vis.append(lines(x + i - start, y + self.bottom, 
                                 x + i - start, y + self.height))
            i += max(unit // 10, 1)


        # make main hashes
        
        # find starting local coord
        seqi = unit * ((start + self.coords.align2local(max(0, worldx1 - x), 
                                                        clamp=True)) // unit) \
                                                        - start-1
        # find starting align coord
        i = self.coords.local2align(seqi)
        endseqi = min(self.coords.align2local(end, clamp=True), 
                      self.coords.align2local(worldx2-x, clamp=True))
        
        # draw all hashes in view
        while seqi <= endseqi:
            vis.append(self.maincolor)
            vis.append(lines(x + i+1, y, x + i+1, y + self.height))
            vis.append(self.text_color)
            vis.append(text(str(int((seqi+start+1)//unit2)) + unitstr, 
                            x + i+1, y, x + i+1 - unit, y + self.height, 
                            self.text_align, "right"))
            seqi += unit
            i = self.coords.local2align(seqi, clamp=True)

        # base line
        vis.append(lines(self.maincolor, x, y, x + end - start, y))

        return group(* vis)
Exemplo n.º 2
0
class RulerTrack(Track):
    """Track for displaying a base-pair ruler along the genome"""
    def __init__(self,
                 top=2.0,
                 bottom=0.0,
                 minicolor=color(.8, .8, .8),
                 maincolor=color(0, 0, 0),
                 align=None,
                 text_align="middle",
                 text_color=color(0, 0, 0),
                 show=True,
                 fixed_height=True,
                 **options):

        Track.__init__(self, **options)
        self.top = top
        self.bottom = bottom
        self.minicolor = minicolor
        self.maincolor = maincolor
        self.text_align = text_align
        self.text_color = text_color
        self.show = show
        self.shown = show
        self.fixed_height = fixed_height

        if align != None:
            self.coords = alignlib.CoordConverter(align)
        else:
            self.coords = None

        self.multiscale = Multiscale(marginx=.5,
                                     marginy=.5,
                                     scalex=10,
                                     scaley=10)

    def draw(self):
        self.multiscale.init(self.get_window())

        self.start = self.view.start - 1
        self.end = self.view.end
        self.height = self.top
        self.multiscale.reset()

        self.gid = group()
        return group(self.gid)

    def update(self):
        self.win = self.get_window()

        if not self.show:
            if self.shown:
                self.gid = self.win.replace_group(self.gid, group())
                self.shown = False
        else:
            self.shown = True

            if not self.multiscale.same_view():
                if self.coords == None:
                    g = self.draw_ruler(self.pos, self.start, self.end)
                else:
                    g = self.draw_align_ruler(self.pos, self.start, self.end)
                self.gid = self.win.replace_group(self.gid, g)

    def set_visible(self, visible):
        self.show = visible

    def draw_ruler(self, pos, start, end):
        worldx1, worldy1, worldx2, worldy2 = self.win.get_visible()
        screenwidth, screenheight = self.win.get_size()

        worldwidth = worldx2 - worldx1
        worldx1 -= worldwidth / 2.0
        worldx2 += worldwidth / 2.0

        # find appropriate unit if one is not given
        unit = visual.getRulerAutoSize(screenwidth, worldwidth)
        order = int(math.log10(unit))
        unit2, unitstr = visual.getUnitSuffix(unit)

        x, y = pos
        vis = []

        # make mini hashes
        if unit >= 10:
            vis.append(self.minicolor)
            i = unit * (max(start, worldx1 - x + start) // unit)
            while x + i - start <= worldx2 and i < end:
                if i >= start:
                    vis.append(
                        lines(x + i - start, y + self.bottom, x + i - start,
                              y + self.top))
                i += unit // 10

        # make main hashes
        i = unit * (max(start, worldx1 - x + start) // unit)
        while x + i - start <= worldx2 and i < end:
            if i >= start:
                vis.append(self.maincolor)
                vis.append(lines(x + i - start, y, x + i - start,
                                 y + self.top))
                vis.append(self.text_color)
                vis.append(
                    text(
                        str(int(i // unit2)) + unitstr, x + i - start, y,
                        x + i - start - unit, y + self.top, self.text_align,
                        "right"))
            i += unit

        # base line
        vis.append(lines(self.maincolor, x, y, x + end - start, y))

        return group(*vis)

    def draw_align_ruler(self, pos, start, end):
        worldx1, worldy1, worldx2, worldy2 = self.win.get_visible()
        screenwidth, screenheight = self.win.get_size()

        worldwidth = worldx2 - worldx1
        worldx1 -= worldwidth / 2.0
        worldx2 += worldwidth / 2.0

        # find appropriate unit if one is not given
        unit = visual.getRulerAutoSize(screenwidth, worldwidth)
        order = int(math.log10(unit))
        unit2, unitstr = visual.getUnitSuffix(unit)

        x, y = pos
        vis = []

        # make mini hashes
        vis.append(self.minicolor)
        i = unit * (max(start, worldx1 - x + start) // unit)
        while x + i - start <= worldx2 and i < end:
            if i >= start:
                vis.append(
                    lines(x + i - start, y + self.bottom, x + i - start,
                          y + self.height))
            i += max(unit // 10, 1)

        # make main hashes

        # find starting local coord
        seqi = unit * ((start + self.coords.align2local(max(0, worldx1 - x),
                                                        clamp=True)) // unit) \
                                                        - start-1
        # find starting align coord
        i = self.coords.local2align(seqi)
        endseqi = min(self.coords.align2local(end, clamp=True),
                      self.coords.align2local(worldx2 - x, clamp=True))

        # draw all hashes in view
        while seqi <= endseqi:
            vis.append(self.maincolor)
            vis.append(lines(x + i + 1, y, x + i + 1, y + self.height))
            vis.append(self.text_color)
            vis.append(
                text(
                    str(int((seqi + start + 1) // unit2)) + unitstr, x + i + 1,
                    y, x + i + 1 - unit, y + self.height, self.text_align,
                    "right"))
            seqi += unit
            i = self.coords.local2align(seqi, clamp=True)

        # base line
        vis.append(lines(self.maincolor, x, y, x + end - start, y))

        return group(*vis)