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
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
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
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
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
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
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
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