1 """Represent information for graphical display.
2
3 Classes in this module are designed to hold information in a way that
4 makes it easy to draw graphical figures.
5 """
6
7 from reportlab.lib import colors
8
9
10 from Bio.Graphics.BasicChromosome import ChromosomeSegment
11 from Bio.Graphics.BasicChromosome import TelomereSegment
12
13
14
15
16 RAINBOW_COLORS = {(1, 1) : colors.violet,
17 (2, 2) : colors.indigo,
18 (3, 3) : colors.blue,
19 (4, 4) : colors.green,
20 (5, 5) : colors.yellow,
21 (6, 6) : colors.orange,
22 (7, 20) : colors.red}
23
24
26 """Represent a chromosome with count information.
27
28 This is used to display information about counts along a chromosome.
29 The segments are expected to have different count information, which
30 will be displayed using a color scheme.
31
32 I envision using this class when you think that certain regions of
33 the chromosome will be especially abundant in the counts, and you
34 want to pick those out.
35 """
37 """Initialize a representation of chromosome counts.
38
39 Arguments:
40
41 o segment_names - An ordered list of all segment names along
42 the chromosome. The count and other information will be added to
43 these.
44
45 o color_scheme - A coloring scheme to use in the counts. This should
46 be a dictionary mapping count ranges to colors (specified in
47 reportlab.lib.colors).
48 """
49 self._names = segment_names
50 self._count_info = {}
51 self._label_info = {}
52 self._scale_info = {}
53 for name in self._names:
54 self._count_info[name] = 0
55 self._label_info[name] = None
56 self._scale_info[name] = 1
57
58 self._color_scheme = color_scheme
59
60 - def add_count(self, segment_name, count = 1):
61 """Add counts to the given segment name.
62
63 Arguments:
64
65 o segment_name - The name of the segment we should add counts to.
66 If the name is not present, a KeyError will be raised.
67
68 o count - The counts to add the current segment. This defaults to
69 a single count.
70 """
71 try:
72 self._count_info[segment_name] += count
73 except KeyError:
74 raise KeyError("Segment name %s not found." % segment_name)
75
77 """Divide the counts for a segment by some kind of scale value.
78
79 This is useful if segments aren't represented by raw counts, but
80 are instead counts divided by some number.
81 """
82 try:
83 self._count_info[segment_name] = \
84 float(self._count_info[segment_name]) / float(scale_value)
85 except KeyError:
86 raise KeyError("Segment name %s not found." % segment_name)
87
89 """Add a label to a specfic segment.
90
91 Raises a KeyError is the specified segment name is not found.
92 """
93 if segment_name in self._label_info:
94 self._label_info[segment_name] = label
95 else:
96 raise KeyError("Segment name %s not found." % segment_name)
97
99 """Set the scale for a specific chromosome segment.
100
101 By default all segments have the same scale -- this allows scaling
102 by the size of the segment.
103
104 Raises a KeyError is the specified segment name is not found.
105 """
106 if segment_name in self._label_info:
107 self._scale_info[segment_name] = scale
108 else:
109 raise KeyError("Segment name %s not found." % segment_name)
110
112 """Retrieve the color and label info about the segments.
113
114 Returns a list consiting of two tuples specifying the counts and
115 label name for each segment. The list is ordered according to the
116 original listing of names. Labels are set as None if no label
117 was specified.
118 """
119 order_info = []
120
121 for seg_name in self._names:
122 order_info.append((self._count_info[seg_name],
123 self._label_info[seg_name]))
124
125 return order_info
126
128 """Add the collected segment information to a chromosome for drawing.
129
130 Arguments:
131
132 o chromosome - A Chromosome graphics object that we can add
133 chromosome segments to.
134
135 This creates ChromosomeSegment (and TelomereSegment) objects to
136 fill in the chromosome. The information is derived from the
137 label and count information, with counts transformed to the
138 specified color map.
139
140 Returns the chromosome with all of the segments added.
141 """
142 for seg_num in range(len(self._names)):
143 is_end_segment = 0
144
145 if seg_num == 0:
146 cur_segment = TelomereSegment()
147 is_end_segment = 1
148 elif seg_num == len(self._names) - 1:
149 cur_segment = TelomereSegment(1)
150 is_end_segment = 1
151
152 else:
153 cur_segment = ChromosomeSegment()
154
155 seg_name = self._names[seg_num]
156 if self._count_info[seg_name] > 0:
157 color = self._color_from_count(self._count_info[seg_name])
158 cur_segment.fill_color = color
159
160 if self._label_info[seg_name] is not None:
161 cur_segment.label = self._label_info[seg_name]
162
163
164 if is_end_segment:
165 cur_segment.scale = 3
166 else:
167 cur_segment.scale = self._scale_info[seg_name]
168
169 chromosome.add(cur_segment)
170
171 return chromosome
172
174 """Translate the given count into a color using the color scheme.
175 """
176 for count_start, count_end in self._color_scheme:
177 if count >= count_start and count <= count_end:
178 return self._color_scheme[(count_start, count_end)]
179
180
181 raise ValueError("Count value %s was not found in the color scheme."
182 % count)
183