1
2
3
4
5
6
7
8
9
10
11
12 """ LinearDrawer module
13
14 Provides:
15
16 o LinearDrawer - Drawing object for linear diagrams
17
18 For drawing capabilities, this module uses reportlab to draw and write
19 the diagram:
20
21 http://www.reportlab.com
22
23 For dealing with biological information, the package expects BioPython
24 objects:
25
26 http://www.biopython.org
27 """
28
29
30 from reportlab.graphics.shapes import *
31 from reportlab.lib import colors
32
33
34 from _AbstractDrawer import AbstractDrawer, draw_box, draw_arrow
35 from _AbstractDrawer import intermediate_points, angle2trig
36 from _FeatureSet import FeatureSet
37 from _GraphSet import GraphSet
38
39 from math import ceil
40
42 """ LinearDrawer(AbstractDrawer)
43
44 Inherits from:
45
46 o AbstractDrawer
47
48 Provides:
49
50 Methods:
51
52 o __init__(self, parent=None, pagesize='A3', orientation='landscape',
53 x=0.05, y=0.05, xl=None, xr=None, yt=None, yb=None,
54 start=None, end=None, tracklines=0, fragments=10,
55 fragment_size=0.9, track_size=0.75) Called on instantiation
56
57 o set_page_size(self, pagesize, orientation) Set the page size to the
58 passed size and orientation
59
60 o set_margins(self, x, y, xl, xr, yt, yb) Set the drawable area of the
61 page
62
63 o set_bounds(self, start, end) Set the bounds for the elements to be
64 drawn
65
66 o is_in_bounds(self, value) Returns a boolean for whether the position
67 is actually to be drawn
68
69 o __len__(self) Returns the length of sequence that will be drawn
70
71
72 o draw(self) Place the drawing elements on the diagram
73
74 o init_fragments(self) Calculate information
75 about sequence fragment locations on the drawing
76
77 o set_track_heights(self) Calculate information about the offset of
78 each track from the fragment base
79
80 o draw_test_tracks(self) Add lines demarcating each track to the
81 drawing
82
83 o draw_track(self, track) Return the contents of the passed track as
84 drawing elements
85
86 o draw_scale(self, track) Return a scale for the passed track as
87 drawing elements
88
89 o draw_tick(self, tickpos, ctr, ticklen, track, draw_label) Return a
90 tick line and possibly a label
91
92 o draw_greytrack(self, track) Return a grey background and superposed
93 label for the passed track as drawing
94 elements
95
96 o draw_feature_set(self, set) Return the features in the passed set as
97 drawing elements
98
99 o draw_feature(self, feature) Return a single feature as drawing
100 elements
101
102 o get_feature_sigil(self, feature, x0, x1, fragment) Return a single
103 feature as its sigil in drawing elements
104
105 o draw_graph_set(self, set) Return the data in a set of graphs as
106 drawing elements
107
108 o draw_line_graph(self, graph) Return the data in a graph as a line
109 graph in drawing elements
110
111 o draw_heat_graph(self, graph) Return the data in a graph as a heat
112 graph in drawing elements
113
114 o draw_bar_graph(self, graph) Return the data in a graph as a bar
115 graph in drawing elements
116
117 o canvas_location(self, base) Return the fragment, and the offset from
118 the left margin, of a passed position
119 in the sequence, on the diagram.
120
121 Attributes:
122
123 o tracklines Boolean for whether to draw lines dilineating tracks
124
125 o pagesize Tuple describing the size of the page in pixels
126
127 o x0 Float X co-ord for leftmost point of drawable area
128
129 o xlim Float X co-ord for rightmost point of drawable area
130
131 o y0 Float Y co-ord for lowest point of drawable area
132
133 o ylim Float Y co-ord for topmost point of drawable area
134
135 o pagewidth Float pixel width of drawable area
136
137 o pageheight Float pixel height of drawable area
138
139 o xcenter Float X co-ord of center of drawable area
140
141 o ycenter Float Y co-ord of center of drawable area
142
143 o start Int, base to start drawing from
144
145 o end Int, base to stop drawing at
146
147 o length Int, size of sequence to be drawn
148
149 o fragments Int, number of fragments into which to divide the
150 drawn sequence
151
152 o fragment_size Float (0->1) the proportion of the fragment height to
153 draw in
154
155 o track_size Float (0->1) the proportion of the track height to
156 draw in
157
158 o drawing Drawing canvas
159
160 o drawn_tracks List of ints denoting which tracks are to be drawn
161
162 o current_track_level Int denoting which track is currently being
163 drawn
164
165 o fragment_height Float total fragment height in pixels
166
167 o fragment_bases Int total fragment length in bases
168
169 o fragment_lines Dictionary of top and bottom y-coords of fragment,
170 keyed by fragment number
171
172 o fragment_limits Dictionary of start and end bases of each fragment,
173 keyed by fragment number
174
175 o track_offsets Dictionary of number of pixels that each track top,
176 center and bottom is offset from the base of a
177 fragment, keyed by track
178
179 """
180 - def __init__(self, parent=None, pagesize='A3', orientation='landscape',
181 x=0.05, y=0.05, xl=None, xr=None, yt=None, yb=None,
182 start=None, end=None, tracklines=0, fragments=10,
183 fragment_size=0.9, track_size=0.75):
184 """ __init__(self, parent, pagesize='A3', orientation='landscape',
185 x=0.05, y=0.05, xl=None, xr=None, yt=None, yb=None,
186 start=None, end=None, tracklines=0, fragments=10,
187 fragment_size=0.9, track_size=0.75)
188
189 o parent Diagram object containing the data that the drawer
190 draws
191
192 o pagesize String describing the ISO size of the image, or a tuple
193 of pixels
194
195 o orientation String describing the required orientation of the
196 final drawing ('landscape' or 'portrait')
197
198 o x Float (0->1) describing the relative size of the X
199 margins to the page
200
201 o y Float (0->1) describing the relative size of the Y
202 margins to the page
203
204 o xl Float (0->1) describing the relative size of the left X
205 margin to the page (overrides x)
206
207 o xl Float (0->1) describing the relative size of the left X
208 margin to the page (overrides x)
209
210 o xr Float (0->1) describing the relative size of the right X
211 margin to the page (overrides x)
212
213 o yt Float (0->1) describing the relative size of the top Y
214 margin to the page (overrides y)
215
216 o yb Float (0->1) describing the relative size of the lower Y
217 margin to the page (overrides y)
218
219 o start Int, the position to begin drawing the diagram at
220
221 o end Int, the position to stop drawing the diagram at
222
223 o tracklines Boolean flag to show (or not) lines delineating tracks
224 on the diagram
225
226 o fragments Int, the number of equal fragments into which the
227 sequence should be divided for drawing
228
229 o fragment_size Float(0->1) The proportion of the available height
230 for the fragment that should be taken up in drawing
231
232 o track_size The proportion of the available track height that
233 should be taken up in drawing
234
235 """
236
237 AbstractDrawer.__init__(self, parent, pagesize, orientation,
238 x, y, xl, xr, yt, yb, start, end,
239 tracklines)
240
241
242 self.fragments = fragments
243 self.fragment_size = fragment_size
244 self.track_size = track_size
245
246
248 """ draw(self)
249
250 Draw a linear diagram of the data in the parent Diagram object
251 """
252
253 self.drawing = Drawing(self.pagesize[0], self.pagesize[1])
254
255 feature_elements = []
256 feature_labels = []
257 greytrack_bgs = []
258 greytrack_labels = []
259 scale_axes = []
260 scale_labels = []
261
262
263 self.drawn_tracks = self._parent.get_drawn_levels()
264
265
266 self.init_fragments()
267 self.set_track_heights()
268
269
270
271 for track_level in self.drawn_tracks:
272 self.current_track_level = track_level
273 track = self._parent[track_level]
274 gbgs, glabels = self.draw_greytrack(track)
275 greytrack_bgs.append(gbgs)
276 greytrack_labels.append(glabels)
277 features, flabels = self.draw_track(track)
278 feature_elements.append(features)
279 feature_labels.append(flabels)
280 if track.scale:
281 axes, slabels = self.draw_scale(track)
282 scale_axes.append(axes)
283 scale_labels.append(slabels)
284
285
286
287
288
289
290
291
292 element_groups = [greytrack_bgs, feature_elements, scale_axes,
293 scale_labels, feature_labels, greytrack_labels]
294 for element_group in element_groups:
295 for element_list in element_group:
296 [self.drawing.add(element) for element in element_list]
297
298 if self.tracklines:
299 self.draw_test_tracks()
300
301
303 """ init_fragments(self)
304
305 Initialises useful values for calculating the positioning of
306 diagram elements
307 """
308
309 self.fragment_height = 1.*self.pageheight/self.fragments
310 self.fragment_bases = ceil(1.*self.length/self.fragments)
311
312
313 self.fragment_lines = {}
314 fragment_crop = (1-self.fragment_size)/2
315 fragy = self.ylim
316 for fragment in range(self.fragments):
317 fragtop = fragy-fragment_crop * self.fragment_height
318 fragbtm = fragy-(1-fragment_crop) * self.fragment_height
319 self.fragment_lines[fragment] = (fragbtm, fragtop)
320 fragy -= self.fragment_height
321
322
323 self.fragment_limits = {}
324 fragment_step = self.fragment_bases
325 fragment_count = 0
326
327 for marker in range(int(self.start), int(self.end), int(fragment_step)):
328 self.fragment_limits[fragment_count] = (marker, marker+fragment_step)
329 fragment_count += 1
330
331
333 """ set_track_heights(self)
334
335 Since tracks may not be of identical heights, the bottom and top
336 offsets of each track relative to the fragment top and bottom is
337 stored in a dictionary - self.track_offsets, keyed by track number
338 """
339 top_track = max(self.drawn_tracks)
340
341 trackunit_sum = 0
342 trackunits = {}
343 heightholder = 0
344 for track in range(1, top_track+1):
345 try:
346 trackheight = self._parent[track].height
347 except:
348 trackheight = 1
349 trackunit_sum += trackheight
350 trackunits[track] = (heightholder, heightholder+trackheight)
351 heightholder += trackheight
352 trackunit_height = 1.*self.fragment_height*self.fragment_size/trackunit_sum
353
354
355
356 track_offsets = {}
357 track_crop = trackunit_height*(1-self.track_size)/2.
358 assert track_crop >= 0
359 for track in trackunits:
360 top = trackunits[track][1]*trackunit_height-track_crop
361 btm = trackunits[track][0]*trackunit_height+track_crop
362 ctr = btm+(top-btm)/2.
363 track_offsets[track] = (btm, ctr, top)
364 self.track_offsets = track_offsets
365
366
368 """ draw_test_tracks(self)
369
370 Draw red lines indicating the top and bottom of each fragment,
371 and blue ones indicating tracks to be drawn.
372 """
373
374 for fbtm, ftop in self.fragment_lines.values():
375 self.drawing.add(Line(self.x0, ftop, self.xlim, ftop,
376 strokeColor=colors.red))
377 self.drawing.add(Line(self.x0, fbtm, self.xlim, fbtm,
378 strokeColor=colors.red))
379
380
381 for track in self.drawn_tracks:
382 trackbtm = fbtm + self.track_offsets[track][0]
383 trackctr = fbtm + self.track_offsets[track][1]
384 tracktop = fbtm + self.track_offsets[track][2]
385 self.drawing.add(Line(self.x0, tracktop, self.xlim, tracktop,
386 strokeColor=colors.blue))
387 self.drawing.add(Line(self.x0, trackctr, self.xlim, trackctr,
388 strokeColor=colors.green))
389 self.drawing.add(Line(self.x0, trackbtm, self.xlim, trackbtm,
390 strokeColor=colors.blue))
391
392
394 """ draw_track(self, track) -> ([element, element,...], [element, element,...])
395
396 o track Track object
397
398 Returns a tuple (list of elements in the track, list of labels in
399 the track)
400 """
401 track_elements = []
402 track_labels = []
403
404
405 set_methods = {FeatureSet: self.draw_feature_set,
406 GraphSet: self.draw_graph_set
407 }
408
409 for set in track.get_sets():
410 elements, labels = set_methods[set.__class__](set)
411 track_elements += elements
412 track_labels += labels
413 return track_elements, track_labels
414
415
416 - def draw_tick(self, tickpos, ctr, ticklen, track, draw_label):
417 """ draw_tick(self, tickpos, ctr, ticklen) -> (element, element)
418
419 o tickpos Int, position of the tick on the sequence
420
421 o ctr Float, Y co-ord of the center of the track
422
423 o ticklen How long to draw the tick
424
425 o track Track, the track the tick is drawn on
426
427 o draw_label Boolean, write the tick label?
428
429 Returns a drawing element that is the tick on the scale
430 """
431 assert self.start <= tickpos and tickpos <= self.end, \
432 "Tick at %i, but showing %i to %i" \
433 % (tickpos, self.start, self.end)
434 fragment, tickx = self.canvas_location(tickpos)
435 assert fragment >=0, \
436 "Fragment %i, tickpos %i" % (fragment, tickpos)
437 tctr = ctr + self.fragment_lines[fragment][0]
438 tickx += self.x0
439 ticktop = tctr + ticklen
440 tick = Line(tickx, tctr, tickx, ticktop, strokeColor=track.scale_color)
441 if draw_label:
442 if track.scale_format == 'SInt':
443 if tickpos >= 1000000:
444 tickstring = str(tickpos//1000000) + " Mbp"
445 elif tickpos >= 1000:
446 tickstring = str(tickpos//1000) + " Kbp"
447 else:
448 tickstring = str(tickpos)
449 else:
450 tickstring = str(tickpos)
451 label = String(0, 0, tickstring,
452 fontName=track.scale_font,
453 fontSize=track.scale_fontsize,
454 fillColor=track.scale_color)
455 labelgroup = Group(label)
456 rotation = angle2trig(track.scale_fontangle)
457 labelgroup.transform = (rotation[0], rotation[1], rotation[2],
458 rotation[3], tickx, ticktop)
459 else:
460 labelgroup = None
461 return tick, labelgroup
462
464 """ draw_scale(self, track) -> ([element, element,...], [element, element,...])
465
466 o track Track object
467
468 Returns a tuple of (list of elements in the scale, list of labels
469 in the scale)
470 """
471 scale_elements = []
472 scale_labels = []
473
474 if not track.scale:
475 return [], []
476
477
478 btm, ctr, top = self.track_offsets[self.current_track_level]
479 trackheight = (top-ctr)
480
481
482 for fragment in range(self.fragments):
483 tbtm = btm + self.fragment_lines[fragment][0]
484 tctr = ctr + self.fragment_lines[fragment][0]
485 ttop = top + self.fragment_lines[fragment][0]
486
487 if fragment == self.fragments - 1:
488 frag, x = self.canvas_location(self.end)
489 scale_elements.append(Line(self.x0, tctr, self.x0 + x, tctr,
490 strokeColor=track.scale_color))
491 else:
492 scale_elements.append(Line(self.x0, tctr, self.xlim, tctr,
493 strokeColor=track.scale_color))
494
495 scale_elements.append(Line(self.x0, tbtm, self.x0, ttop,
496 strokeColor=track.scale_color))
497 if track.scale_ticks:
498
499
500
501
502
503 ticklen = track.scale_largeticks * trackheight
504 tickiterval = int(track.scale_largetick_interval)
505
506
507
508
509 largeticks = [pos for pos \
510 in range(tickiterval * (self.start//tickiterval),
511 int(self.end),
512 tickiterval) \
513 if pos >= self.start]
514 for tickpos in largeticks:
515 tick, label = self.draw_tick(tickpos, ctr, ticklen,
516 track,
517 track.scale_largetick_labels)
518 scale_elements.append(tick)
519 if label is not None:
520 scale_labels.append(label)
521
522 ticklen = track.scale_smallticks * trackheight
523 tickiterval = int(track.scale_smalltick_interval)
524 smallticks = [pos for pos \
525 in range(tickiterval * (self.start//tickiterval),
526 int(self.end),
527 tickiterval) \
528 if pos >= self.start]
529 for tickpos in smallticks:
530 tick, label = self.draw_tick(tickpos, ctr, ticklen,
531 track,
532 track.scale_smalltick_labels)
533 scale_elements.append(tick)
534 if label is not None:
535 scale_labels.append(label)
536
537
538
539 if track.axis_labels:
540 for set in track.get_sets():
541 if set.__class__ is GraphSet:
542 graph_label_min = []
543 graph_label_mid = []
544 graph_label_max = []
545 for graph in set.get_graphs():
546 quartiles = graph.quartiles()
547 minval, maxval = quartiles[0], quartiles[4]
548 if graph.center is None:
549 midval = (maxval + minval)/2.
550 graph_label_min.append("%.3f" % minval)
551 graph_label_max.append("%.3f" % maxval)
552 else:
553 diff = max((graph.center-minval),
554 (maxval-graph.center))
555 minval = graph.center-diff
556 maxval = graph.center+diff
557 midval = graph.center
558 graph_label_mid.append("%.3f" % midval)
559 graph_label_min.append("%.3f" % minval)
560 graph_label_max.append("%.3f" % maxval)
561 for fragment in range(self.fragments):
562 tbtm = btm + self.fragment_lines[fragment][0]
563 tctr = ctr + self.fragment_lines[fragment][0]
564 ttop = top + self.fragment_lines[fragment][0]
565 for val, pos in [(";".join(graph_label_min), tbtm),
566 (";".join(graph_label_max), ttop),
567 (";".join(graph_label_mid), tctr)]:
568 label = String(0, 0, val,
569 fontName=track.scale_font,
570 fontSize=track.scale_fontsize,
571 fillColor=track.scale_color)
572 labelgroup = Group(label)
573 rotation = angle2trig(track.scale_fontangle)
574 labelgroup.transform = (rotation[0], rotation[1], rotation[2],
575 rotation[3], self.x0, pos)
576 scale_labels.append(labelgroup)
577
578 return scale_elements, scale_labels
579
580
581
583 """ draw_greytrack(self) -> ([element, element,...], [element, element,...])
584
585 o track Track object
586
587 Put in a grey background to the current track in all fragments,
588 if track specifies that we should
589 """
590 greytrack_bgs = []
591 greytrack_labels = []
592
593 if not track.greytrack:
594 return [], []
595
596
597 btm, ctr, top = self.track_offsets[self.current_track_level]
598
599
600 for fragment in range(self.fragments):
601 tbtm = btm + self.fragment_lines[fragment][0]
602 tctr = ctr + self.fragment_lines[fragment][0]
603 ttop = top + self.fragment_lines[fragment][0]
604 box = draw_box((self.x0, tbtm), (self.xlim, ttop),
605 colors.Color(0.96,0.96, 0.96))
606 greytrack_bgs.append(box)
607
608 if track.greytrack_labels:
609 labelstep = (self.pagewidth)/track.greytrack_labels
610 label = String(0, 0, track.name,
611 fontName=track.greytrack_font,
612 fontSize=track.greytrack_fontsize,
613 fillColor=track.greytrack_fontcolor)
614
615 for x in range(int(self.x0), int(self.xlim), int(labelstep)):
616 labelgroup = Group(label)
617 rotation = angle2trig(track.greytrack_font_rotation)
618 labelgroup.transform = (rotation[0], rotation[1], rotation[2],
619 rotation[3], x, tbtm)
620 if not self.xlim-x <= labelstep:
621 greytrack_labels.append(labelgroup)
622
623 return greytrack_bgs, greytrack_labels
624
625
627 """ draw_feature_set(self, set) -> ([element, element,...], [element, element,...])
628
629 o set FeatureSet object
630
631 Returns a tuple (list of elements describing features, list of
632 labels for elements)
633 """
634
635 feature_elements = []
636 label_elements = []
637
638
639 for feature in set.get_features():
640 if self.is_in_bounds(feature.start) or self.is_in_bounds(feature.end):
641 features, labels = self.draw_feature(feature)
642 feature_elements += features
643 label_elements += labels
644
645 return feature_elements, label_elements
646
647
649 """ draw_feature(self, feature, parent_feature=None) -> ([element, element,...], [element, element,...])
650
651 o feature Feature containing location info
652
653 Returns tuple of (list of elements describing single feature, list
654 of labels for those elements)
655 """
656 if feature.hide:
657 return [], []
658
659 feature_elements = []
660 label_elements = []
661
662
663 for start, end in feature.locations:
664
665
666 if start > end:
667 locs = [(start, self.end), (self.start, end)]
668 else:
669 locs = [(start, end)]
670
671 for locstart, locend in locs:
672
673
674 if locstart < self.start:
675 locstart = self.start
676 if locend > self.end:
677 locend = self.end
678
679 feature_boxes = self.draw_feature_location(feature, locstart, locend)
680 for box, label in feature_boxes:
681 feature_elements.append(box)
682 if label is not None:
683 label_elements.append(label)
684
685 return feature_elements, label_elements
686
688 feature_boxes = []
689
690 start_fragment, start_offset = self.canvas_location(locstart)
691 end_fragment, end_offset = self.canvas_location(locend)
692
693
694
695
696
697
698
699
700 allowed_fragments = self.fragment_limits.keys()
701 if start_fragment in allowed_fragments and end_fragment in allowed_fragments:
702
703
704 if start_fragment == end_fragment:
705 feature_box, label = self.get_feature_sigil(feature, start_offset,
706 end_offset, start_fragment)
707 feature_boxes.append((feature_box, label))
708
709
710
711 else:
712 fragment = start_fragment
713 start = start_offset
714
715
716 while self.fragment_limits[fragment][1] < locend:
717
718 feature_box, label = self.get_feature_sigil(feature, start,
719 self.pagewidth,
720 fragment)
721
722 fragment += 1
723 start = 0
724 feature_boxes.append((feature_box, label))
725
726
727
728
729
730
731 feature_box, label = self.get_feature_sigil(feature, 0,
732 end_offset, fragment)
733 feature_boxes.append((feature_box, label))
734
735
736 return feature_boxes
737
738
739
741 """ get_feature_sigil(self, feature, x0, x1, fragment) -> (element, element, element)
742
743 o feature Feature object
744
745 o x0 Start X co-ordinate on diagram
746
747 o x1 End X co-ordinate on diagram
748
749 o fragment The fragment on which the feature appears
750
751 Returns a drawable indicator of the feature, and any required label
752 for it
753 """
754
755 x0, x1 = self.x0 + x0, self.x0 + x1
756 btm, ctr, top = self.track_offsets[self.current_track_level]
757 try:
758 btm += self.fragment_lines[fragment][0]
759 ctr += self.fragment_lines[fragment][0]
760 top += self.fragment_lines[fragment][0]
761 except:
762 print "We've got a screw-up"
763 print self.start, self.end
764 print self.fragment_bases
765 print x0, x1
766 for locstart, locend in feature.locations:
767 print self.canvas_location(locstart)
768 print self.canvas_location(locend)
769 print 'FEATURE\n', feature
770 1/0
771
772
773
774
775 draw_methods = {'BOX': draw_box,
776 'ARROW': draw_arrow,
777 }
778 method = draw_methods[feature.sigil]
779 kwargs['head_length_ratio'] = feature.arrowhead_length
780 kwargs['shaft_height_ratio'] = feature.arrowshaft_height
781
782
783
784 if hasattr(feature, "url") :
785 kwargs["hrefURL"] = feature.url
786 kwargs["hrefTitle"] = feature.name
787
788 strand = feature.strand
789
790
791 if strand == 1:
792 sigil = method((x0, ctr), (x1, top), color=feature.color,
793 orientation='right', **kwargs)
794 elif strand == -1:
795 sigil = method((x1, btm), (x0, ctr), color=feature.color,
796 orientation='left', **kwargs)
797 else:
798 sigil = method((x0, btm), (x1, top), color=feature.color,
799 **kwargs)
800 if feature.label:
801 label = String(0, 0, feature.name,
802 fontName=feature.label_font,
803 fontSize=feature.label_size,
804 fillColor=feature.label_color)
805 labelgroup = Group(label)
806
807
808 if feature.strand in (0, 1):
809 rotation = angle2trig(feature.label_angle)
810 if feature.label_position in ('start', "5'", 'left'):
811 pos = x0
812 elif feature.label_position in ('middle', 'center', 'centre'):
813 pos = (x1 + x0)/2.
814 else:
815 pos = x1
816 labelgroup.transform = (rotation[0], rotation[1], rotation[2],
817 rotation[3], pos, top)
818 else:
819 rotation = angle2trig(feature.label_angle + 180)
820 if feature.label_position in ('start', "5'", 'left'):
821 pos = x1
822 elif feature.label_position in ('middle', 'center', 'centre'):
823 pos = (x1 + x0)/2.
824 else:
825 pos = x0
826 labelgroup.transform = (rotation[0], rotation[1], rotation[2],
827 rotation[3], pos, btm)
828 else:
829 labelgroup = None
830 return sigil, labelgroup
831
832
834 """ draw_graph_set(self, set) -> ([element, element,...], [element, element,...])
835
836 o set GraphSet object
837
838 Returns tuple (list of graph elements, list of graph labels)
839 """
840
841 elements = []
842
843
844 style_methods = {'line': self.draw_line_graph,
845 'heat': self.draw_heat_graph,
846 'bar': self.draw_bar_graph
847 }
848
849 for graph in set.get_graphs():
850 elements += style_methods[graph.style](graph)
851
852 return elements, []
853
854
856 """ draw_line_graph(self, graph) -> [element, element,...]
857
858 o graph Graph object
859
860 Returns a line graph as a list of drawable elements
861 """
862
863 line_elements = []
864
865
866 data_quartiles = graph.quartiles()
867 minval, maxval = data_quartiles[0],data_quartiles[4]
868 btm, ctr, top = self.track_offsets[self.current_track_level]
869 trackheight = 0.5*(top-btm)
870 datarange = maxval - minval
871 if datarange == 0:
872 datarange = trackheight
873 data = graph[self.start:self.end]
874
875
876
877 if graph.center is None:
878 midval = (maxval + minval)/2.
879 else:
880 midval = graph.center
881
882
883
884 resolution = max((midval-minval), (maxval-midval))
885
886
887 pos, val = data[0]
888 lastfrag, lastx = self.canvas_location(pos)
889 lastx += self.x0
890 lasty = trackheight*(val-midval)/resolution + \
891 self.fragment_lines[lastfrag][0] + ctr
892 lastval = val
893
894 for pos, val in data:
895 frag, x = self.canvas_location(pos)
896 x += self.x0
897 y = trackheight*(val-midval)/resolution + \
898 self.fragment_lines[frag][0] + ctr
899 if frag == lastfrag:
900 line_elements.append(Line(lastx, lasty, x, y,
901 strokeColor = graph.poscolor,
902 strokeWidth = graph.linewidth))
903 else:
904 tempval = 1.*(val-lastval)/(x-lastx)
905 tempy = trackheight*(val-midval)/resolution + \
906 self.fragment_lines[lastfrag][0] + ctr
907 line_elements.append(Line(lastx, lasty, self.xlim, tempy,
908 strokeColor = graph.poscolor,
909 strokeWidth = graph.linewidth))
910 tempy = trackheight*(val-midval)/resolution + \
911 self.fragment_lines[frag][0] + ctr
912 line_elements.append(Line(self.x0, tempy, x, y,
913 strokeColor = graph.poscolor,
914 strokeWidth = graph.linewidth))
915 lastfrag, lastx, lasty, lastval = frag, x, y, val
916
917 return line_elements
918
919
921 """ draw_heat_graph(self, graph) -> [element, element,...]
922
923 o graph Graph object
924
925 Returns a list of drawable elements for the heat graph
926 """
927
928
929
930
931
932 heat_elements = []
933
934
935 data_quartiles = graph.quartiles()
936 minval, maxval = data_quartiles[0],data_quartiles[4]
937 midval = (maxval + minval)/2.
938 btm, ctr, top = self.track_offsets[self.current_track_level]
939 trackheight = (top-btm)
940
941 newdata = intermediate_points(self.start, self.end,
942 graph[self.start:self.end])
943
944
945
946
947
948 for pos0, pos1, val in newdata:
949 fragment0, x0 = self.canvas_location(pos0)
950 fragment1, x1 = self.canvas_location(pos1)
951 x0, x1 = self.x0 + x0, self.x0 + x1
952
953
954
955
956 heat = colors.linearlyInterpolatedColor(graph.poscolor,
957 graph.negcolor,
958 maxval, minval, val)
959
960
961 if fragment0 == fragment1:
962 if pos1 >= self.fragment_limits[fragment0][1]:
963 x1 = self.xlim
964 ttop = top + self.fragment_lines[fragment0][0]
965 tbtm = btm + self.fragment_lines[fragment0][0]
966
967
968 heat_elements.append(draw_box((x0, tbtm), (x1, ttop),
969 color=heat, border=None))
970 else:
971
972
973 fragment = fragment0
974 start = x0
975 while self.fragment_limits[fragment][1] <= pos1:
976
977 ttop = top + self.fragment_lines[fragment][0]
978 tbtm = btm + self.fragment_lines[fragment][0]
979 heat_elements.append(draw_box((start, tbtm),
980 (self.xlim, ttop),
981 color=heat,
982 border=None))
983 fragment += 1
984 start = self.x0
985 ttop = top + self.fragment_lines[fragment][0]
986 tbtm = btm + self.fragment_lines[fragment][0]
987
988
989 heat_elements.append(draw_box((self.x0, tbtm), (x1, ttop),
990 color=heat, border=None))
991
992 return heat_elements
993
994
996 """ draw_bar_graph(self, graph) -> [element, element,...]
997
998 o graph Graph object
999
1000 Returns a list of drawable elements for a bar graph of the passed
1001 Graph object
1002 """
1003
1004
1005
1006
1007
1008 bar_elements = []
1009
1010
1011 data_quartiles = graph.quartiles()
1012 minval, maxval = data_quartiles[0],data_quartiles[4]
1013 btm, ctr, top = self.track_offsets[self.current_track_level]
1014 trackheight = 0.5*(top-btm)
1015 datarange = maxval - minval
1016 if datarange == 0:
1017 datarange = trackheight
1018 data = graph[self.start:self.end]
1019
1020
1021 if graph.center is None:
1022 midval = (maxval + minval)/2.
1023 else:
1024 midval = graph.center
1025
1026
1027
1028
1029 newdata = intermediate_points(self.start, self.end,
1030 graph[self.start:self.end])
1031
1032
1033
1034
1035 resolution = max((midval-minval), (maxval-midval))
1036 if resolution == 0:
1037 resolution = trackheight
1038
1039
1040 for pos0, pos1, val in newdata:
1041 fragment0, x0 = self.canvas_location(pos0)
1042 fragment1, x1 = self.canvas_location(pos1)
1043 x0, x1 = self.x0 + x0, self.x0 + x1
1044 barval = trackheight*(val-midval)/resolution
1045 if barval >=0:
1046 barcolor = graph.poscolor
1047 else:
1048 barcolor = graph.negcolor
1049
1050
1051 if fragment0 == fragment1:
1052 if pos1 >= self.fragment_limits[fragment0][1]:
1053 x1 = self.xlim
1054 tctr = ctr + self.fragment_lines[fragment0][0]
1055 barval += tctr
1056 bar_elements.append(draw_box((x0, tctr), (x1, barval),
1057 color=barcolor))
1058 else:
1059 fragment = fragment0
1060
1061
1062 start = x0
1063 while self.fragment_limits[fragment][1] < pos1:
1064 tctr = ctr + self.fragment_lines[fragment][0]
1065 thisbarval = barval + tctr
1066 bar_elements.append(draw_box((start, tctr),
1067 (self.xlim, thisbarval),
1068 color=barcolor))
1069 fragment += 1
1070 start = self.x0
1071 tctr = ctr + self.fragment_lines[fragment1][0]
1072 barval += tctr
1073
1074 bar_elements.append(draw_box((self.x0, tctr), (x1, barval),
1075 color=barcolor))
1076
1077 return bar_elements
1078
1079
1081 """ canvas_location(self, base) -> (int, float)
1082
1083 o base The base number on the genome sequence
1084
1085 Returns the x-coordinate and fragment number of a base on the
1086 genome sequence, in the context of the current drawing setup
1087 """
1088 base = int(base - self.start)
1089 fragment = int(base / self.fragment_bases)
1090 if fragment < 1:
1091 base_offset = base
1092 fragment = 0
1093 else:
1094 base_offset = base % self.fragment_bases
1095
1096 x_offset = 1. * self.pagewidth * base_offset / self.fragment_bases
1097 return fragment, x_offset
1098