bio-graphics 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/doc/classes/Bio.html +135 -0
- data/doc/classes/Bio/Graphics.html +247 -0
- data/doc/classes/Bio/Graphics/Panel.html +344 -0
- data/doc/classes/Bio/Graphics/Panel.src/M000005.html +29 -0
- data/doc/classes/Bio/Graphics/Panel.src/M000006.html +19 -0
- data/doc/classes/Bio/Graphics/Panel.src/M000007.html +67 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.html +238 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000008.html +20 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000009.html +28 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000010.html +54 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000013.html +20 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000014.html +28 -0
- data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000015.html +59 -0
- data/doc/classes/Bio/Graphics/Panel/Track.html +342 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000008.html +23 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000009.html +42 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000010.html +285 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000011.html +23 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000012.html +43 -0
- data/doc/classes/Bio/Graphics/Panel/Track.src/M000013.html +259 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature.html +292 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature.src/M000011.html +65 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature.src/M000014.html +65 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.html +155 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.src/M000012.html +18 -0
- data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.src/M000015.html +18 -0
- data/doc/classes/ImageMap.html +185 -0
- data/doc/classes/ImageMap.src/M000001.html +18 -0
- data/doc/classes/ImageMap.src/M000002.html +24 -0
- data/doc/classes/ImageMap/ImageMapElement.html +187 -0
- data/doc/classes/ImageMap/ImageMapElement.src/M000003.html +19 -0
- data/doc/classes/ImageMap/ImageMapElement.src/M000004.html +20 -0
- data/doc/created.rid +1 -0
- data/doc/files/README_DEV.html +432 -0
- data/doc/files/TUTORIAL.html +358 -0
- data/doc/files/lib/bio-graphics_rb.html +121 -0
- data/doc/files/lib/bio/graphics/feature_rb.html +113 -0
- data/doc/files/lib/bio/graphics/image_map_rb.html +113 -0
- data/doc/files/lib/bio/graphics/panel_rb.html +113 -0
- data/doc/files/lib/bio/graphics/ruler_rb.html +113 -0
- data/doc/files/lib/bio/graphics/track_rb.html +113 -0
- data/doc/fr_class_index.html +35 -0
- data/doc/fr_file_index.html +34 -0
- data/doc/fr_method_index.html +41 -0
- data/doc/images/example.png +0 -0
- data/doc/images/glyph_showcase.png +0 -0
- data/doc/images/terms.png +0 -0
- data/doc/images/terms.svg +166 -0
- data/doc/index.html +24 -0
- data/images/example.png +0 -0
- data/images/glyph_showcase.png +0 -0
- data/images/terms.png +0 -0
- data/images/terms.svg +166 -0
- data/lib/bio-graphics.rb +18 -0
- data/lib/bio/graphics/feature.rb +136 -0
- data/lib/bio/graphics/image_map.rb +37 -0
- data/lib/bio/graphics/panel.rb +205 -0
- data/lib/bio/graphics/ruler.rb +96 -0
- data/lib/bio/graphics/track.rb +387 -0
- data/samples/arkdb_features.rb +37 -0
- data/samples/data.txt +32 -0
- data/samples/glyph_showcase.rb +29 -0
- metadata +137 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html>
|
7
|
+
<head>
|
8
|
+
<title>new (ImageMap::ImageMapElement)</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
|
+
</head>
|
12
|
+
<body class="standalone-code">
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/bio/graphics/image_map.rb, line 25</span>
|
14
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">left</span>, <span class="ruby-identifier">top</span>, <span class="ruby-identifier">right</span>, <span class="ruby-identifier">bottom</span>, <span class="ruby-identifier">url</span> = <span class="ruby-keyword kw">nil</span>)
|
15
|
+
<span class="ruby-ivar">@left</span>, <span class="ruby-ivar">@top</span>, <span class="ruby-ivar">@right</span>, <span class="ruby-ivar">@bottom</span> = <span class="ruby-identifier">left</span>, <span class="ruby-identifier">top</span>, <span class="ruby-identifier">right</span>, <span class="ruby-identifier">bottom</span>
|
16
|
+
<span class="ruby-ivar">@url</span> = ( <span class="ruby-identifier">url</span>.<span class="ruby-identifier">nil?</span> ) <span class="ruby-operator">?</span> <span class="ruby-value str">''</span> <span class="ruby-operator">:</span> <span class="ruby-identifier">url</span>
|
17
|
+
<span class="ruby-keyword kw">end</span></pre>
|
18
|
+
</body>
|
19
|
+
</html>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html>
|
7
|
+
<head>
|
8
|
+
<title>to_s (ImageMap::ImageMapElement)</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
|
11
|
+
</head>
|
12
|
+
<body class="standalone-code">
|
13
|
+
<pre><span class="ruby-comment cmt"># File lib/bio/graphics/image_map.rb, line 31</span>
|
14
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">to_s</span>
|
15
|
+
<span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@url</span> <span class="ruby-operator">==</span> <span class="ruby-value str">''</span>
|
16
|
+
<span class="ruby-keyword kw">return</span> <span class="ruby-value str">'<area shape="rect" coords="'</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@left</span>.<span class="ruby-identifier">to_s</span> <span class="ruby-operator">+</span> <span class="ruby-value str">' '</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@top</span>.<span class="ruby-identifier">to_s</span> <span class="ruby-operator">+</span> <span class="ruby-value str">' '</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@right</span>.<span class="ruby-identifier">to_s</span> <span class="ruby-operator">+</span> <span class="ruby-value str">' '</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@bottom</span>.<span class="ruby-identifier">to_s</span> <span class="ruby-operator">+</span> <span class="ruby-value str">'" href="'</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@url</span> <span class="ruby-operator">+</span> <span class="ruby-value str">'"/>'</span>
|
17
|
+
<span class="ruby-keyword kw">end</span>
|
18
|
+
<span class="ruby-keyword kw">end</span></pre>
|
19
|
+
</body>
|
20
|
+
</html>
|
data/doc/created.rid
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Mon Oct 01 11:03:19 +0100 2007
|
@@ -0,0 +1,432 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>File: README.DEV</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="fileHeader">
|
50
|
+
<h1>README.DEV</h1>
|
51
|
+
<table class="header-table">
|
52
|
+
<tr class="top-aligned-row">
|
53
|
+
<td><strong>Path:</strong></td>
|
54
|
+
<td>README.DEV
|
55
|
+
</td>
|
56
|
+
</tr>
|
57
|
+
<tr class="top-aligned-row">
|
58
|
+
<td><strong>Last Update:</strong></td>
|
59
|
+
<td>Mon Oct 01 11:03:17 +0100 2007</td>
|
60
|
+
</tr>
|
61
|
+
</table>
|
62
|
+
</div>
|
63
|
+
<!-- banner header -->
|
64
|
+
|
65
|
+
<div id="bodyContent">
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
<div id="contextContent">
|
70
|
+
|
71
|
+
<div id="description">
|
72
|
+
<p>
|
73
|
+
Copyright (C) 2007 Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
74
|
+
</p>
|
75
|
+
<h2>README for developers</h2>
|
76
|
+
<p>
|
77
|
+
This README is mainly meant to explain how the code works (rather than how
|
78
|
+
to <em>use</em> the library). It should help if you‘re interested in
|
79
|
+
contributing, or if you think you found a bug.
|
80
|
+
</p>
|
81
|
+
<h3>Overview</h3>
|
82
|
+
<p>
|
83
|
+
I‘ve tried to document as much as possible in the code itself, see
|
84
|
+
for example the comments that accompany the setting of the defaults for <a
|
85
|
+
href="../classes/Bio/Graphics.html">Bio::Graphics</a> in the panel.rb file.
|
86
|
+
However, the bigger picture can not be explained that way.
|
87
|
+
</p>
|
88
|
+
<h3>The files</h3>
|
89
|
+
<p>
|
90
|
+
There‘s one file for each class: panel, track, feature, ruler and
|
91
|
+
image_map. See the tutorial on a breakdown what each of these do. All of
|
92
|
+
these except the image_map make up a picture. The image_map is used to
|
93
|
+
describe the HTML map that can be created to make a picture clickable.
|
94
|
+
</p>
|
95
|
+
<p>
|
96
|
+
Classes are embedded in each other: instead of
|
97
|
+
</p>
|
98
|
+
<pre>
|
99
|
+
Bio::Graphics::Panel
|
100
|
+
Bio::Graphics::Ruler
|
101
|
+
Bio::Graphics::Track
|
102
|
+
Bio::Graphics::Feature
|
103
|
+
</pre>
|
104
|
+
<p>
|
105
|
+
we have:
|
106
|
+
</p>
|
107
|
+
<pre>
|
108
|
+
Bio::Graphics::Panel
|
109
|
+
Bio::Graphics::Panel::Ruler
|
110
|
+
Bio::Graphics::Panel::Track
|
111
|
+
Bio::Graphics::Panel::Track::Feature
|
112
|
+
</pre>
|
113
|
+
<p>
|
114
|
+
There‘s a reason for this. A track can only exist within the confines
|
115
|
+
of a panel (i.e. a panel is a container for tracks), and a feature can only
|
116
|
+
exist within the confines of a track. In addition, there are quite some
|
117
|
+
instances where information from the panel is necessary for the track, and
|
118
|
+
from the track for the features.
|
119
|
+
</p>
|
120
|
+
<h3>The workflow</h3>
|
121
|
+
<h4>1. Creating the panel</h4>
|
122
|
+
<p>
|
123
|
+
The user has to start with a
|
124
|
+
</p>
|
125
|
+
<pre>
|
126
|
+
my_panel = Bio::Graphics::Panel.new(length, width, clickable, display_start, display_stop)
|
127
|
+
</pre>
|
128
|
+
<p>
|
129
|
+
When this happens, among other things, the instance variable @tracks is
|
130
|
+
created that will later contain the actual Track objects. In addition,
|
131
|
+
there‘s @number_of_times_bumped. You‘ll later see that each
|
132
|
+
Track object also has its @number_of_times_bumped. The panel needs this
|
133
|
+
information to know how far it has to go down before it can start drawing a
|
134
|
+
track: the first track will be just below the ruler, but the vertical
|
135
|
+
coordinates of the second one depend on the height of all the ones that
|
136
|
+
were drawn previously. And <em>that</em> in turn is defined by the number
|
137
|
+
of times a feature would overlap with another one and therefore had to be
|
138
|
+
<em>bumped</em> down.
|
139
|
+
</p>
|
140
|
+
<p>
|
141
|
+
@display_start and @display_stop are used for zooming in on a region. Even
|
142
|
+
though the full @length of the sequence can be really long, setting
|
143
|
+
@display_start and @display_stop will only consider that region.
|
144
|
+
</p>
|
145
|
+
<p>
|
146
|
+
Then there is @rescale_factor, which plays a crucial role in drawing the
|
147
|
+
stuff: it tells the script how many basepairs are contained in one pixel.
|
148
|
+
This variable will be used <em>very</em> extensively in the drawing code.
|
149
|
+
</p>
|
150
|
+
<p>
|
151
|
+
So this covered the Panel#initialize…
|
152
|
+
</p>
|
153
|
+
<h4>2. Adding tracks to the panel</h4>
|
154
|
+
<p>
|
155
|
+
Because tracks are inherently part of a panel and cannot exist on their
|
156
|
+
own, they can only be created by using a Panel method rather than a Track
|
157
|
+
method.
|
158
|
+
</p>
|
159
|
+
<pre>
|
160
|
+
my_track_1 = my_panel.add_track(name, feature_colour = [0,0,1], feature_glyph = 'generic')
|
161
|
+
</pre>
|
162
|
+
<p>
|
163
|
+
This creates a new Track object and adds it to the @tracks array of the
|
164
|
+
Panel object. Several instance variables are set for the Track object,
|
165
|
+
including @features (which is an array of Feature objects for that track)
|
166
|
+
and @number_of_times_bumped. Every time a feature cannot be drawn because
|
167
|
+
it would overlap with another one, it will be ‘bumped’ down
|
168
|
+
until it can be drawn. This effectively results in <em>rows</em> that
|
169
|
+
contain the features. The @number_of_times_bumped is just the number of
|
170
|
+
rows (to be able to calculate the height of the track afterwards). I admit
|
171
|
+
that this variable should be renamed to something like
|
172
|
+
@number_of_feature_rows or something, because the value is actually the
|
173
|
+
number of times bumped + 1. In the example below, @number_of_times_bumped
|
174
|
+
is 3 (instead of 2). (I‘ll change that later…)
|
175
|
+
</p>
|
176
|
+
<pre>
|
177
|
+
------------------------------------------------------
|
178
|
+
******* **** ********* ***** *****
|
179
|
+
***** ********
|
180
|
+
**
|
181
|
+
</pre>
|
182
|
+
<p>
|
183
|
+
The Panel#add_track method returns the Track object itself, because the
|
184
|
+
latter has to be accessible to be able to assign features to it.
|
185
|
+
</p>
|
186
|
+
<h4>3. Adding features to a track</h4>
|
187
|
+
<p>
|
188
|
+
Same thing as adding a track to a panel: the feature can only be added by
|
189
|
+
the user by using the Track#add_feature method. Parameters are the name of
|
190
|
+
the feature, the location and the link.
|
191
|
+
</p>
|
192
|
+
<p>
|
193
|
+
The location of a feature can be something like
|
194
|
+
‘complement(join(10..20,50..70))’. To be able to parse this, I
|
195
|
+
use the Bio::Locations object from bioruby (see <a
|
196
|
+
href="http://www.bioruby.org">www.bioruby.org</a>). A Bio::Locations
|
197
|
+
(plural) object contains one or more Bio::Location (singular) objects,
|
198
|
+
which are the subfeatures: 10..20 and 50..70. It‘s these
|
199
|
+
Bio::Location objects we use to calculate the ultimate start and stop of
|
200
|
+
the feature.
|
201
|
+
</p>
|
202
|
+
<p>
|
203
|
+
The Track#add_feature method returns the Track object itself.
|
204
|
+
</p>
|
205
|
+
<p>
|
206
|
+
Now let‘s look at the other end: the Feature object that gets
|
207
|
+
created. In the Feature#initialize method, you‘ll notice, apart from
|
208
|
+
the obvious variables, the following instances variables:
|
209
|
+
@pixel_range_collection, @chopped_at_start, @chopped_at_stop,
|
210
|
+
@hidden_subfeatures_at_start and @hidden_subfeatures_at_stop. Let‘s
|
211
|
+
take these one by one:
|
212
|
+
</p>
|
213
|
+
<h5>@pixel_range_collection</h5>
|
214
|
+
<p>
|
215
|
+
Now <em>this</em> is the crucial bit: it will hold the information on what
|
216
|
+
pixels (on the horizontal axis) should be covered. This means that any part
|
217
|
+
of the feature that does not fall within the view is <em>not</em> in this
|
218
|
+
collection. Basically, for every subfeature (e.g. exon for a gene), the
|
219
|
+
location of that subfeature is compared to the region of the view. If a
|
220
|
+
subfeature is not in the view at all, its positions are discarded (but
|
221
|
+
other stuff does happen, see below); if a subfeature is at the left of the
|
222
|
+
picture but actually extends outwith the view, the start pixel will become
|
223
|
+
1. You get the picture. Also see the mini diagrams in the code itself.
|
224
|
+
</p>
|
225
|
+
<p>
|
226
|
+
These start and stop positions are used to create
|
227
|
+
Bio::Graphics::Panel::Track::PixelRange objects. Unspliced objects will
|
228
|
+
have an array @pixel_range_collection with just one element.
|
229
|
+
</p>
|
230
|
+
<h5>@chopped_at_start and @chopped_at_stop</h5>
|
231
|
+
<p>
|
232
|
+
Suppose you‘ve got a directed feature (so one with an arrow), and the
|
233
|
+
3’ end falls outside of the view. What would happen, is that the
|
234
|
+
3’ end that‘s out of view would be chopped of (that‘s
|
235
|
+
good), but also that the end of the glyph (which is <em>not</em> the end of
|
236
|
+
the feature) becomes an arrow. I don‘t want that. Instead, the arrow
|
237
|
+
should be removed.
|
238
|
+
</p>
|
239
|
+
<p>
|
240
|
+
That‘s where the @chopped_at_start and @chopped_at_stop come in. If
|
241
|
+
these are set to true (while building the @pixel_range_collection), the
|
242
|
+
arrow is not drawn.
|
243
|
+
</p>
|
244
|
+
<h5>@hidden_subfeatures_at_start and @hidden_subfeatures_at_stop</h5>
|
245
|
+
<p>
|
246
|
+
For spliced features, it might be that one or more of the subfeatures (e.g.
|
247
|
+
exons) lies outwith the view. We normally draw e.g. genes by drawing the
|
248
|
+
exons as boxes and connecting them with small lines. The drawing code
|
249
|
+
itself (see later) takes all exons within view and draws those connections.
|
250
|
+
However, if an exon is outside of the viewing area, this line is not drawn.
|
251
|
+
The @hidden_subfeatures_at_start and @hidden_subfeatures_at_stop are just
|
252
|
+
flags to capture this.
|
253
|
+
</p>
|
254
|
+
<h4>4. Drawing the thing</h4>
|
255
|
+
<p>
|
256
|
+
The Cairo library (<a
|
257
|
+
href="http://cairographics.org">cairographics.org</a>) is used for the
|
258
|
+
actual drawing. The main concepts in the Cairo drawing model are (please
|
259
|
+
also see <a
|
260
|
+
href="http://cairographics.org/tutorial">cairographics.org/tutorial</a>):
|
261
|
+
</p>
|
262
|
+
<ul>
|
263
|
+
<li><b>source</b>: the <em>paint</em> you‘ll be using
|
264
|
+
|
265
|
+
</li>
|
266
|
+
<li><b>destination</b>: the <em>surface</em> (Cairo::ImageSurface) that you
|
267
|
+
want to draw onto
|
268
|
+
|
269
|
+
</li>
|
270
|
+
<li><b>mask</b>: controls where you apply the source to the destination. Stuff
|
271
|
+
like ‘line_to’.
|
272
|
+
|
273
|
+
</li>
|
274
|
+
<li><b>context</b>: tracks one source, one mask and one destination.
|
275
|
+
|
276
|
+
</li>
|
277
|
+
</ul>
|
278
|
+
<p>
|
279
|
+
From the cairo tutorial: "Before you can start to draw something with
|
280
|
+
cairo, you need to create the context. <SNIP> When you create a cairo
|
281
|
+
context, it must be tied to a specific surface - for example, an image
|
282
|
+
surface if you want to create a PNG file." So that‘s what we
|
283
|
+
have to do: create a Cairo::ImageSurface and connect a Cairo::Context to
|
284
|
+
it.
|
285
|
+
</p>
|
286
|
+
<p>
|
287
|
+
Now let‘s walk through the code itself…
|
288
|
+
</p>
|
289
|
+
<p>
|
290
|
+
When a user draws a panel, the first thing that happens, is the creation of
|
291
|
+
a Cairo::ImageSurface (the <em>destination</em>). To be able to do this, we
|
292
|
+
need to know the dimensions. But there‘s a slight problem: we
|
293
|
+
can‘t know the height of the picture until it‘s actually drawn.
|
294
|
+
The way we‘ll circumvent this, is that we create a really high
|
295
|
+
picture (called "huge_panel_drawing") that we‘ll crop
|
296
|
+
afterwards.
|
297
|
+
</p>
|
298
|
+
<h5>Drawing the ruler</h5>
|
299
|
+
<p>
|
300
|
+
A ruler consists of a line with tickmarks on it. The major issue with
|
301
|
+
drawing the ruler, is determining the distance between those ticks. Suppose
|
302
|
+
we have zoomed into a small region, we‘d still want to see usable
|
303
|
+
ticks; and if we‘ve zoomed out to a huge region, we don‘t want
|
304
|
+
to have those ticks all bumping into each other.
|
305
|
+
</p>
|
306
|
+
<p>
|
307
|
+
To calculate the distance between consecutive ticks, we start with a
|
308
|
+
distance of 1 basepair, and increase it until the minimal distance
|
309
|
+
criterion is met. We also set the distance between major tickmarks (which
|
310
|
+
are the ones that will get a number). There‘s a small issue when you
|
311
|
+
actually start drawing the ticks. Most of the time, we don‘t want the
|
312
|
+
first tick on the very first basepair of the view. Suppose that would be
|
313
|
+
position 333 in the sequence. Then the numbers under the major tickmarks
|
314
|
+
would be: 343, 353, 363, 373 and so on. Instead, we want 350, 360, 370,
|
315
|
+
380. So we want to find the position of the first tick. If we‘ve
|
316
|
+
found that one, it‘s simple to add the rest of them.
|
317
|
+
</p>
|
318
|
+
<p>
|
319
|
+
The ruler height @height consists of the height of the ruler itself plus
|
320
|
+
the height of the numbers.
|
321
|
+
</p>
|
322
|
+
<h5>Drawing the tracks</h5>
|
323
|
+
<p>
|
324
|
+
Drawing each track starts out with the general header: a line above it and
|
325
|
+
the title. Obviously, the more challenging part is drawing the features
|
326
|
+
themselves.
|
327
|
+
</p>
|
328
|
+
<p>
|
329
|
+
First thing we have to do, is figure out what the <b>vertical</b>
|
330
|
+
<b>coordinates</b> of the glyph should be (i.e. the row). To keep track of
|
331
|
+
what parts of the screen are already occupied by features (so that we know
|
332
|
+
when a new feature has to be bumped down), I make use of a <b>grid</b>. The
|
333
|
+
grid is basically a hash with the keys being the row number, and the values
|
334
|
+
arrays of ranges. (These ranges use basepair units rather than pixels, but
|
335
|
+
that‘s completely arbitrary.) For each feature, we first check if we
|
336
|
+
can draw it at the top of the track (i.e. row 1) and if we can‘t move
|
337
|
+
it down a row at a time until there‘s room for it.
|
338
|
+
</p>
|
339
|
+
<p>
|
340
|
+
So for example, suppose we‘ve already drawn two features that have
|
341
|
+
the following positions: 100..150 and 200..225. The grid would then look
|
342
|
+
like this:
|
343
|
+
</p>
|
344
|
+
<pre>
|
345
|
+
grid = { 1 => [(100..150),(200..225)] }
|
346
|
+
</pre>
|
347
|
+
<p>
|
348
|
+
If we‘d like to draw a new feature from 125..175 (which overlaps the
|
349
|
+
first of the two ranges above), we see that row_available becomes false,
|
350
|
+
and the row number is increased. The grid after adding this feature looks
|
351
|
+
like:
|
352
|
+
</p>
|
353
|
+
<pre>
|
354
|
+
grid = { 1 => [(100..150),(200..225)],
|
355
|
+
2 => [(125..175)] }
|
356
|
+
</pre>
|
357
|
+
<p>
|
358
|
+
So now we know what the vertical coordinates of the glyph should be. Next
|
359
|
+
step is to check if there‘s reasons we would like to <b>change</b>
|
360
|
+
<b>the</b> <b>requested</b> <b>glyph</b> <b>type</b> <b>from</b>
|
361
|
+
<b>directed</b> <b>to</b> <b>undirected</b>. If the user asks for directed
|
362
|
+
glyphs (i.e. ones with an arrow at the end), but the view is zoomed
|
363
|
+
<em>way</em> out, there‘s no way the arrow will be visible. If
|
364
|
+
we‘d try to draw that arrow anyway, it would become bigger than the
|
365
|
+
feature itself. Another reason would be if the feature‘s 3’ end
|
366
|
+
extends outwith the picture.
|
367
|
+
</p>
|
368
|
+
<p>
|
369
|
+
Finally, we can <b>draw</b>. The actual drawing bit should be quite
|
370
|
+
self-explanatory (<em>move_to</em>, <em>line_to</em>, …).
|
371
|
+
</p>
|
372
|
+
<p>
|
373
|
+
For the spliced features (<em>spliced</em> itself and
|
374
|
+
<em>directed_spliced</em>), we first draw the components (i.e. the exons)
|
375
|
+
keeping track of the start and stop positions of the gaps (i.e. introns).
|
376
|
+
We then add the connections in those gaps. In addition, we draw a line that
|
377
|
+
extends to the side of the picture if there are exons out of view. This
|
378
|
+
flag was set when the feature was created (see above:
|
379
|
+
@hidden_subfeatures_at_start and @hidden_subfeatures_at_stop).
|
380
|
+
</p>
|
381
|
+
<p>
|
382
|
+
When the user wants a clickable map, we also have to record that this
|
383
|
+
region should be added to the image map.
|
384
|
+
</p>
|
385
|
+
<p>
|
386
|
+
When everything has been drawn, we finally know the number of rows for that
|
387
|
+
track (i.e. the number_of_times_bumped).
|
388
|
+
</p>
|
389
|
+
<h5>Finalizing the panel</h5>
|
390
|
+
<p>
|
391
|
+
So now we have a huge panel (see "huge_panel_drawing" above)
|
392
|
+
which is way to high. This is converted to a panel of the right size by
|
393
|
+
creating a new panel (i.e. the cairo destination), and then using the huge
|
394
|
+
panel as a source to be transferred on that new destination.
|
395
|
+
</p>
|
396
|
+
<p>
|
397
|
+
And we just write the PNG to a file. If the user wanted a clickable map,
|
398
|
+
also create the HTML file.
|
399
|
+
</p>
|
400
|
+
|
401
|
+
</div>
|
402
|
+
|
403
|
+
|
404
|
+
</div>
|
405
|
+
|
406
|
+
|
407
|
+
</div>
|
408
|
+
|
409
|
+
|
410
|
+
<!-- if includes -->
|
411
|
+
|
412
|
+
<div id="section">
|
413
|
+
|
414
|
+
|
415
|
+
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
|
420
|
+
|
421
|
+
<!-- if method_list -->
|
422
|
+
|
423
|
+
|
424
|
+
</div>
|
425
|
+
|
426
|
+
|
427
|
+
<div id="validator-badges">
|
428
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
429
|
+
</div>
|
430
|
+
|
431
|
+
</body>
|
432
|
+
</html>
|