Example #1
0
    def draw_tick(self, tickpos, ctr, ticklen, track, draw_label):
        """ draw_tick(self, tickpos, ctr, ticklen) -> (element, element)

            o tickpos   Int, position of the tick on the sequence

            o ctr       Float, Y co-ord of the center of the track

            o ticklen   How long to draw the tick

            o track     Track, the track the tick is drawn on

            o draw_label    Boolean, write the tick label?

            Returns a drawing element that is the tick on the scale
        """
        assert self.start <= tickpos and tickpos <= self.end, \
               "Tick at %i, but showing %i to %i" \
               % (tickpos, self.start, self.end)
        fragment, tickx = self.canvas_location(tickpos)  # Tick co-ordinates
        assert fragment >=0, \
               "Fragment %i, tickpos %i" % (fragment, tickpos)
        tctr = ctr + self.fragment_lines[fragment][
            0]  # Center line of the track
        tickx += self.x0  # Tick X co-ord
        ticktop = tctr + ticklen  # Y co-ord of tick top
        tick = Line(tickx, tctr, tickx, ticktop, strokeColor=track.scale_color)
        if draw_label:  # Put tick position on as label
            if track.scale_format == 'SInt':
                if tickpos >= 1000000:
                    tickstring = str(tickpos / 1000000) + " Mbp"
                elif tickpos >= 1000:
                    tickstring = str(tickpos / 1000) + " Kbp"
                else:
                    tickstring = str(tickpos)
            else:
                tickstring = str(tickpos)
            label = String(
                0,
                0,
                tickstring,  # Make label string
                fontName=track.scale_font,
                fontSize=track.scale_fontsize,
                fillColor=track.scale_color)
            labelgroup = Group(label)
            rotation = angle2trig(track.scale_fontangle)
            labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                    rotation[3], tickx, ticktop)
        else:
            labelgroup = None
        return tick, labelgroup
Example #2
0
    def draw_greytrack(self, track):
        """ draw_greytrack(self) -> ([element, element,...], [element, element,...])

            o track     Track object

            Put in a grey background to the current track in all fragments,
            if track specifies that we should
        """
        greytrack_bgs = []  # Holds grey track backgrounds
        greytrack_labels = []  # Holds grey foreground labels

        if not track.greytrack:  # No greytrack required, return early
            return [], []

        # Get track location
        btm, ctr, top = self.track_offsets[self.current_track_level]

        # Add greytrack to all fragments for this track
        for fragment in range(self.fragments):
            tbtm = btm + self.fragment_lines[fragment][0]
            tctr = ctr + self.fragment_lines[fragment][0]
            ttop = top + self.fragment_lines[fragment][0]
            box = draw_box(
                (self.x0, tbtm),
                (self.xlim, ttop),  # Grey track bg
                colors.Color(0.98, 0.98, 0.98))  # is just a box
            greytrack_bgs.append(box)

            if track.greytrack_labels:  # If labels are required
                labelstep = (
                    self.pagewidth
                ) / track.greytrack_labels  # how far apart should they be?
                label = String(
                    0,
                    0,
                    track.name,  # label contents
                    fontName=track.greytrack_font,
                    fontSize=track.greytrack_fontsize,
                    fillColor=track.greytrack_fontcolor)
                # Create a new labelgroup at each position the label is required
                for x in range(int(self.x0), int(self.xlim), int(labelstep)):
                    labelgroup = Group(label)
                    rotation = angle2trig(track.greytrack_font_rotation)
                    labelgroup.transform = (rotation[0], rotation[1],
                                            rotation[2], rotation[3], x, tbtm)
                    if not self.xlim - x <= labelstep:  # Don't overlap the end of the track
                        greytrack_labels.append(labelgroup)

        return greytrack_bgs, greytrack_labels
Example #3
0
    def draw_tick(self, tickpos, ctr, ticklen, track, draw_label):
        """ draw_tick(self, tickpos, ctr, ticklen) -> (element, element)

            o tickpos   Int, position of the tick on the sequence

            o ctr       Float, Y co-ord of the center of the track

            o ticklen   How long to draw the tick

            o track     Track, the track the tick is drawn on

            o draw_label    Boolean, write the tick label?

            Returns a drawing element that is the tick on the scale
        """
        assert self.start <= tickpos and tickpos <= self.end, \
               "Tick at %i, but showing %i to %i" \
               % (tickpos, self.start, self.end)
        fragment, tickx = self.canvas_location(tickpos) # Tick co-ordinates
        assert fragment >=0, \
               "Fragment %i, tickpos %i" % (fragment, tickpos)
        tctr = ctr + self.fragment_lines[fragment][0]   # Center line of the track
        tickx += self.x0                # Tick X co-ord
        ticktop = tctr + ticklen        # Y co-ord of tick top
        tick = Line(tickx, tctr, tickx, ticktop, strokeColor=track.scale_color)
        if draw_label: # Put tick position on as label
            if track.scale_format == 'SInt':
                if tickpos >= 1000000:
                    tickstring = str(tickpos/1000000) + " Mbp"
                elif tickpos >= 1000:
                    tickstring = str(tickpos/1000) + " Kbp"
                else:
                    tickstring = str(tickpos)
            else:
                tickstring = str(tickpos)
            label = String(0, 0, tickstring,  # Make label string
                   fontName=track.scale_font,
                   fontSize=track.scale_fontsize,
                   fillColor=track.scale_color)
            labelgroup = Group(label)
            rotation = angle2trig(track.scale_fontangle)
            labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                    rotation[3], tickx, ticktop)
        else:
            labelgroup = None
        return tick, labelgroup
Example #4
0
    def draw_greytrack(self, track):
        """ draw_greytrack(self) -> ([element, element,...], [element, element,...])

            o track     Track object

            Put in a grey background to the current track in all fragments,
            if track specifies that we should
        """        
        greytrack_bgs = []      # Holds grey track backgrounds
        greytrack_labels = []   # Holds grey foreground labels

        if not track.greytrack: # No greytrack required, return early
            return [], []

        # Get track location
        btm, ctr, top = self.track_offsets[self.current_track_level]

        # Add greytrack to all fragments for this track
        for fragment in range(self.fragments):
            tbtm = btm + self.fragment_lines[fragment][0]
            tctr = ctr + self.fragment_lines[fragment][0]
            ttop = top + self.fragment_lines[fragment][0]  
            box = draw_box((self.x0, tbtm), (self.xlim, ttop),  # Grey track bg
                           colors.Color(0.98,0.98, 0.98))       # is just a box
            greytrack_bgs.append(box)

            if track.greytrack_labels:  # If labels are required
                labelstep = (self.pagewidth)/track.greytrack_labels # how far apart should they be?
                label = String(0, 0, track.name,    # label contents
                               fontName=track.greytrack_font,
                               fontSize=track.greytrack_fontsize,
                               fillColor=track.greytrack_fontcolor)
                # Create a new labelgroup at each position the label is required
                for x in range(int(self.x0), int(self.xlim), int(labelstep)):
                    labelgroup = Group(label)
                    rotation = angle2trig(track.greytrack_font_rotation)
                    labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                            rotation[3], x, tbtm)
                    if not self.xlim-x <= labelstep:    # Don't overlap the end of the track
                        greytrack_labels.append(labelgroup)

        return greytrack_bgs, greytrack_labels
Example #5
0
    def get_feature_sigil(self, feature, x0, x1, fragment, **kwargs):
        """ get_feature_sigil(self, feature, x0, x1, fragment) -> (element, element, element)

            o feature       Feature object

            o x0            Start X co-ordinate on diagram

            o x1            End X co-ordinate on diagram

            o fragment      The fragment on which the feature appears

            Returns a drawable indicator of the feature, and any required label
            for it
        """
        # Establish co-ordinates for drawing
        x0, x1 = self.x0 + x0, self.x0 + x1
        btm, ctr, top = self.track_offsets[self.current_track_level]
        try:
            btm += self.fragment_lines[fragment][0]
            ctr += self.fragment_lines[fragment][0]
            top += self.fragment_lines[fragment][0]
        except:  # Only called if the method screws up big time
            print "We've got a screw-up"
            print self.start, self.end
            print self.fragment_bases
            print x0, x1
            for locstart, locend in feature.locations:
                print self.canvas_location(locstart)
                print self.canvas_location(locend)
            print 'FEATURE\n', feature
            1 / 0

        # Distribution dictionary for various ways of drawing the feature
        # Each method takes the corners of a containing box and a color
        # as argument
        draw_methods = {
            'BOX': draw_box,
            'ARROW': draw_arrow,
        }
        method = draw_methods[feature.sigil]
        kwargs['head_length_ratio'] = feature.arrowhead_length
        kwargs['shaft_height_ratio'] = feature.arrowshaft_height

        strand = feature.strand
        # Get sigil for the feature, location dependent on the feature strand
        if strand == 0:
            sigil = method((x0, btm), (x1, top), color=feature.color, **kwargs)
        if strand == 1:
            sigil = method((x0, ctr), (x1, top),
                           color=feature.color,
                           orientation='right',
                           **kwargs)
        if strand == -1:
            sigil = method((x1, btm), (x0, ctr),
                           color=feature.color,
                           orientation='left',
                           **kwargs)
        if feature.label:  # Feature requires a label
            label = String(0,
                           0,
                           feature.name,
                           fontName=feature.label_font,
                           fontSize=feature.label_size,
                           fillColor=feature.label_color)
            labelgroup = Group(label)
            # Feature is on top, or covers both strands (location affects
            # the height and rotation of the label)
            if feature.strand in (0, 1):
                rotation = angle2trig(feature.label_angle)
                if feature.label_position in ('start', "5'", 'left'):
                    pos = x0
                elif feature.label_position in ('middle', 'center', 'centre'):
                    pos = (x1 + x0) / 2.
                else:
                    pos = x1
                labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                        rotation[3], pos, top)
            else:  # Feature on bottom strand
                rotation = angle2trig(feature.label_angle + 180)
                if feature.label_position in ('start', "5'", 'left'):
                    pos = x1
                elif feature.label_position in ('middle', 'center', 'centre'):
                    pos = (x1 + x0) / 2.
                else:
                    pos = x0
                labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                        rotation[3], pos, btm)
        else:
            labelgroup = None
        return sigil, labelgroup
Example #6
0
    def draw_scale(self, track):
        """ draw_scale(self, track) -> ([element, element,...], [element, element,...])

            o track     Track object

            Returns a tuple of (list of elements in the scale, list of labels
            in the scale)
        """
        scale_elements = []  # Holds axes and ticks
        scale_labels = []  # Holds labels

        if not track.scale:  # No scale required, exit early
            return [], []

        # Get track location
        btm, ctr, top = self.track_offsets[self.current_track_level]
        trackheight = (top - ctr)

        # For each fragment, draw the scale for this track
        for fragment in range(self.fragments):
            tbtm = btm + self.fragment_lines[fragment][0]
            tctr = ctr + self.fragment_lines[fragment][0]
            ttop = top + self.fragment_lines[fragment][0]
            # X-axis
            if fragment == self.fragments - 1:
                frag, x = self.canvas_location(self.end)
                scale_elements.append(
                    Line(self.x0,
                         tctr,
                         self.x0 + x,
                         tctr,
                         strokeColor=track.scale_color))
            else:
                scale_elements.append(
                    Line(self.x0,
                         tctr,
                         self.xlim,
                         tctr,
                         strokeColor=track.scale_color))
            # Y-axis
            scale_elements.append(
                Line(self.x0,
                     tbtm,
                     self.x0,
                     ttop,
                     strokeColor=track.scale_color))
        if track.scale_ticks:  # Ticks are required on the scale
            # Draw large ticks
            #I want the ticks to be consistently positioned relative to
            #the start of the sequence (position 0), not relative to the
            #current viewpoint (self.start and self.end)

            ticklen = track.scale_largeticks * trackheight
            tickiterval = int(track.scale_largetick_interval)
            #Note that we could just start the list of ticks using
            #range(0,self.end,tickinterval) and the filter out the
            #ones before self.start - but this seems wasteful.
            #Using tickiterval * (self.start/tickiterval) is a shortcut.
            largeticks = [pos for pos \
                          in range(tickiterval * (self.start/tickiterval),
                                   int(self.end),
                                   tickiterval) \
                          if pos >= self.start]
            for tickpos in largeticks:
                tick, label = self.draw_tick(tickpos, ctr, ticklen, track,
                                             track.scale_largetick_labels)
                scale_elements.append(tick)
                if label is not None:  # If there's a label, add it
                    scale_labels.append(label)
            # Draw small ticks
            ticklen = track.scale_smallticks * trackheight
            tickiterval = int(track.scale_smalltick_interval)
            smallticks = [pos for pos \
                          in range(tickiterval * (self.start/tickiterval),
                                   int(self.end),
                                   tickiterval) \
                          if pos >= self.start]
            for tickpos in smallticks:
                tick, label = self.draw_tick(tickpos, ctr, ticklen, track,
                                             track.scale_smalltick_labels)
                scale_elements.append(tick)
                if label is not None:  # If there's a label, add it
                    scale_labels.append(label)

        # Check to see if the track contains a graph - if it does, get the
        # minimum and maximum values, and put them on the scale Y-axis
        if track.axis_labels:
            for set in track.get_sets():  # Check all sets...
                if set.__class__ is GraphSet:  # ...for a graph set
                    graph_label_min = []
                    graph_label_mid = []
                    graph_label_max = []
                    for graph in set.get_graphs():
                        quartiles = graph.quartiles()
                        minval, maxval = quartiles[0], quartiles[4]
                        if graph.center is None:
                            midval = (maxval + minval) / 2.
                            graph_label_min.append("%.3f" % minval)
                            graph_label_max.append("%.3f" % maxval)
                        else:
                            diff = max((graph.center - minval),
                                       (maxval - graph.center))
                            minval = graph.center - diff
                            maxval = graph.center + diff
                            midval = graph.center
                            graph_label_mid.append("%.3f" % midval)
                            graph_label_min.append("%.3f" % minval)
                            graph_label_max.append("%.3f" % maxval)
                    for fragment in range(
                            self.fragments):  # Add to all fragment axes
                        tbtm = btm + self.fragment_lines[fragment][0]
                        tctr = ctr + self.fragment_lines[fragment][0]
                        ttop = top + self.fragment_lines[fragment][0]
                        for val, pos in [(join(graph_label_min, ';'), tbtm),
                                         (join(graph_label_max, ';'), ttop),
                                         (join(graph_label_mid, ';'), tctr)]:
                            label = String(0,
                                           0,
                                           val,
                                           fontName=track.scale_font,
                                           fontSize=track.scale_fontsize,
                                           fillColor=track.scale_color)
                            labelgroup = Group(label)
                            rotation = angle2trig(track.scale_fontangle)
                            labelgroup.transform = (rotation[0], rotation[1],
                                                    rotation[2], rotation[3],
                                                    self.x0, pos)
                            scale_labels.append(labelgroup)

        return scale_elements, scale_labels
Example #7
0
    def get_feature_sigil(self, feature, x0, x1, fragment, **kwargs):
        """ get_feature_sigil(self, feature, x0, x1, fragment) -> (element, element, element)

            o feature       Feature object

            o x0            Start X co-ordinate on diagram

            o x1            End X co-ordinate on diagram

            o fragment      The fragment on which the feature appears

            Returns a drawable indicator of the feature, and any required label
            for it
        """
        # Establish co-ordinates for drawing
        x0, x1 = self.x0 + x0, self.x0 + x1
        btm, ctr, top = self.track_offsets[self.current_track_level]
        try:
            btm += self.fragment_lines[fragment][0]
            ctr += self.fragment_lines[fragment][0]
            top += self.fragment_lines[fragment][0]
        except:     # Only called if the method screws up big time
            print "We've got a screw-up"
            print self.start, self.end
            print self.fragment_bases
            print x0, x1
            for locstart, locend in feature.locations:
                print self.canvas_location(locstart)
                print self.canvas_location(locend)
            print 'FEATURE\n', feature
            1/0

        # Distribution dictionary for various ways of drawing the feature
        # Each method takes the corners of a containing box and a color
        # as argument
        draw_methods = {'BOX': draw_box,
                        'ARROW': draw_arrow,
                        }
        method = draw_methods[feature.sigil]
        kwargs['head_length_ratio'] = feature.arrowhead_length
        kwargs['shaft_height_ratio'] = feature.arrowshaft_height

        strand = feature.strand
        # Get sigil for the feature, location dependent on the feature strand
        if strand == 0:
            sigil = method((x0, btm), (x1, top), color=feature.color,
                           **kwargs)
        if strand == 1:
            sigil = method((x0, ctr), (x1, top), color=feature.color,
                           orientation='right', **kwargs)
        if strand == -1:
            sigil = method((x1, btm), (x0, ctr), color=feature.color,
                           orientation='left', **kwargs)
        if feature.label:   # Feature requires a label
            label = String(0, 0, feature.name,
                           fontName=feature.label_font,
                           fontSize=feature.label_size,
                           fillColor=feature.label_color)
            labelgroup = Group(label)
            # Feature is on top, or covers both strands (location affects
            # the height and rotation of the label)
            if feature.strand in (0, 1):    
                rotation = angle2trig(feature.label_angle)
                if feature.label_position in ('start', "5'", 'left'):
                    pos = x0
                elif feature.label_position in ('middle', 'center', 'centre'):
                    pos = (x1 + x0)/2.
                else:
                    pos = x1
                labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                        rotation[3], pos, top)
            else:   # Feature on bottom strand
                rotation = angle2trig(feature.label_angle + 180)                        
                if feature.label_position in ('start', "5'", 'left'):
                    pos = x1
                elif feature.label_position in ('middle', 'center', 'centre'):
                    pos = (x1 + x0)/2.
                else:
                    pos = x0
                labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                        rotation[3], pos, btm)
        else:
            labelgroup = None
        return sigil, labelgroup
Example #8
0
    def draw_scale(self, track):
        """ draw_scale(self, track) -> ([element, element,...], [element, element,...])

            o track     Track object

            Returns a tuple of (list of elements in the scale, list of labels
            in the scale)
        """
        scale_elements = []     # Holds axes and ticks
        scale_labels = []       # Holds labels

        if not track.scale:     # No scale required, exit early
            return [], []

        # Get track location
        btm, ctr, top = self.track_offsets[self.current_track_level]
        trackheight = (top-ctr)

        # For each fragment, draw the scale for this track
        for fragment in range(self.fragments):
            tbtm = btm + self.fragment_lines[fragment][0]
            tctr = ctr + self.fragment_lines[fragment][0]
            ttop = top + self.fragment_lines[fragment][0]
            # X-axis
            if fragment == self.fragments - 1:
                frag, x = self.canvas_location(self.end)
                scale_elements.append(Line(self.x0, tctr, self.x0 + x, tctr,
                                       strokeColor=track.scale_color))
            else:
                scale_elements.append(Line(self.x0, tctr, self.xlim, tctr,
                                           strokeColor=track.scale_color))
            # Y-axis
            scale_elements.append(Line(self.x0, tbtm, self.x0, ttop,
                                       strokeColor=track.scale_color))
        if track.scale_ticks:   # Ticks are required on the scale
            # Draw large ticks
            #I want the ticks to be consistently positioned relative to
            #the start of the sequence (position 0), not relative to the
            #current viewpoint (self.start and self.end)

            ticklen = track.scale_largeticks * trackheight
            tickiterval = int(track.scale_largetick_interval)
            #Note that we could just start the list of ticks using
            #range(0,self.end,tickinterval) and the filter out the
            #ones before self.start - but this seems wasteful.
            #Using tickiterval * (self.start/tickiterval) is a shortcut.
            largeticks = [pos for pos \
                          in range(tickiterval * (self.start/tickiterval),
                                   int(self.end),
                                   tickiterval) \
                          if pos >= self.start]
            for tickpos in largeticks:
                tick, label = self.draw_tick(tickpos, ctr, ticklen,
                                             track,
                                             track.scale_largetick_labels)
                scale_elements.append(tick)
                if label is not None:   # If there's a label, add it
                    scale_labels.append(label)
            # Draw small ticks
            ticklen = track.scale_smallticks * trackheight
            tickiterval = int(track.scale_smalltick_interval)
            smallticks = [pos for pos \
                          in range(tickiterval * (self.start/tickiterval),
                                   int(self.end),
                                   tickiterval) \
                          if pos >= self.start]
            for tickpos in smallticks:
                tick, label = self.draw_tick(tickpos, ctr, ticklen,
                                             track,
                                             track.scale_smalltick_labels)
                scale_elements.append(tick)
                if label is not None:   # If there's a label, add it
                    scale_labels.append(label)

        # Check to see if the track contains a graph - if it does, get the
        # minimum and maximum values, and put them on the scale Y-axis
        if track.axis_labels:
            for set in track.get_sets():            # Check all sets...
                if set.__class__ is GraphSet:     # ...for a graph set
                    graph_label_min = []
                    graph_label_mid = []                    
                    graph_label_max = []
                    for graph in set.get_graphs():
                        quartiles = graph.quartiles()
                        minval, maxval = quartiles[0], quartiles[4]
                        if graph.center is None:
                            midval = (maxval + minval)/2.
                            graph_label_min.append("%.3f" % minval)
                            graph_label_max.append("%.3f" % maxval)
                        else:
                            diff = max((graph.center-minval),
                                       (maxval-graph.center))
                            minval = graph.center-diff
                            maxval = graph.center+diff
                            midval = graph.center
                            graph_label_mid.append("%.3f" % midval)
                            graph_label_min.append("%.3f" % minval)
                            graph_label_max.append("%.3f" % maxval)
                    for fragment in range(self.fragments):  # Add to all fragment axes
                        tbtm = btm + self.fragment_lines[fragment][0]
                        tctr = ctr + self.fragment_lines[fragment][0]
                        ttop = top + self.fragment_lines[fragment][0]
                        for val, pos in [(join(graph_label_min, ';'), tbtm),
                                         (join(graph_label_max, ';'), ttop),
                                         (join(graph_label_mid, ';'), tctr)]:
                            label = String(0, 0, val,
                                           fontName=track.scale_font,
                                           fontSize=track.scale_fontsize,
                                           fillColor=track.scale_color)
                            labelgroup = Group(label)
                            rotation = angle2trig(track.scale_fontangle)
                            labelgroup.transform = (rotation[0], rotation[1], rotation[2],
                                                    rotation[3], self.x0, pos)
                            scale_labels.append(labelgroup)

        return scale_elements, scale_labels