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.
Files changed (63) hide show
  1. data/doc/classes/Bio.html +135 -0
  2. data/doc/classes/Bio/Graphics.html +247 -0
  3. data/doc/classes/Bio/Graphics/Panel.html +344 -0
  4. data/doc/classes/Bio/Graphics/Panel.src/M000005.html +29 -0
  5. data/doc/classes/Bio/Graphics/Panel.src/M000006.html +19 -0
  6. data/doc/classes/Bio/Graphics/Panel.src/M000007.html +67 -0
  7. data/doc/classes/Bio/Graphics/Panel/Ruler.html +238 -0
  8. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000008.html +20 -0
  9. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000009.html +28 -0
  10. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000010.html +54 -0
  11. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000013.html +20 -0
  12. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000014.html +28 -0
  13. data/doc/classes/Bio/Graphics/Panel/Ruler.src/M000015.html +59 -0
  14. data/doc/classes/Bio/Graphics/Panel/Track.html +342 -0
  15. data/doc/classes/Bio/Graphics/Panel/Track.src/M000008.html +23 -0
  16. data/doc/classes/Bio/Graphics/Panel/Track.src/M000009.html +42 -0
  17. data/doc/classes/Bio/Graphics/Panel/Track.src/M000010.html +285 -0
  18. data/doc/classes/Bio/Graphics/Panel/Track.src/M000011.html +23 -0
  19. data/doc/classes/Bio/Graphics/Panel/Track.src/M000012.html +43 -0
  20. data/doc/classes/Bio/Graphics/Panel/Track.src/M000013.html +259 -0
  21. data/doc/classes/Bio/Graphics/Panel/Track/Feature.html +292 -0
  22. data/doc/classes/Bio/Graphics/Panel/Track/Feature.src/M000011.html +65 -0
  23. data/doc/classes/Bio/Graphics/Panel/Track/Feature.src/M000014.html +65 -0
  24. data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.html +155 -0
  25. data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.src/M000012.html +18 -0
  26. data/doc/classes/Bio/Graphics/Panel/Track/Feature/PixelRange.src/M000015.html +18 -0
  27. data/doc/classes/ImageMap.html +185 -0
  28. data/doc/classes/ImageMap.src/M000001.html +18 -0
  29. data/doc/classes/ImageMap.src/M000002.html +24 -0
  30. data/doc/classes/ImageMap/ImageMapElement.html +187 -0
  31. data/doc/classes/ImageMap/ImageMapElement.src/M000003.html +19 -0
  32. data/doc/classes/ImageMap/ImageMapElement.src/M000004.html +20 -0
  33. data/doc/created.rid +1 -0
  34. data/doc/files/README_DEV.html +432 -0
  35. data/doc/files/TUTORIAL.html +358 -0
  36. data/doc/files/lib/bio-graphics_rb.html +121 -0
  37. data/doc/files/lib/bio/graphics/feature_rb.html +113 -0
  38. data/doc/files/lib/bio/graphics/image_map_rb.html +113 -0
  39. data/doc/files/lib/bio/graphics/panel_rb.html +113 -0
  40. data/doc/files/lib/bio/graphics/ruler_rb.html +113 -0
  41. data/doc/files/lib/bio/graphics/track_rb.html +113 -0
  42. data/doc/fr_class_index.html +35 -0
  43. data/doc/fr_file_index.html +34 -0
  44. data/doc/fr_method_index.html +41 -0
  45. data/doc/images/example.png +0 -0
  46. data/doc/images/glyph_showcase.png +0 -0
  47. data/doc/images/terms.png +0 -0
  48. data/doc/images/terms.svg +166 -0
  49. data/doc/index.html +24 -0
  50. data/images/example.png +0 -0
  51. data/images/glyph_showcase.png +0 -0
  52. data/images/terms.png +0 -0
  53. data/images/terms.svg +166 -0
  54. data/lib/bio-graphics.rb +18 -0
  55. data/lib/bio/graphics/feature.rb +136 -0
  56. data/lib/bio/graphics/image_map.rb +37 -0
  57. data/lib/bio/graphics/panel.rb +205 -0
  58. data/lib/bio/graphics/ruler.rb +96 -0
  59. data/lib/bio/graphics/track.rb +387 -0
  60. data/samples/arkdb_features.rb +37 -0
  61. data/samples/data.txt +32 -0
  62. data/samples/glyph_showcase.rb +29 -0
  63. 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">'&lt;area shape=&quot;rect&quot; coords=&quot;'</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">'&quot; href=&quot;'</span> <span class="ruby-operator">+</span> <span class="ruby-ivar">@url</span> <span class="ruby-operator">+</span> <span class="ruby-value str">'&quot;/&gt;'</span>
17
+ <span class="ruby-keyword kw">end</span>
18
+ <span class="ruby-keyword kw">end</span></pre>
19
+ </body>
20
+ </html>
@@ -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 &lt;jan.aerts@bbsrc.ac.uk&gt;
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&#8216;re interested in
79
+ contributing, or if you think you found a bug.
80
+ </p>
81
+ <h3>Overview</h3>
82
+ <p>
83
+ I&#8216;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&#8216;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&#8216;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&#8216;s @number_of_times_bumped. You&#8216;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&#8230;
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 &#8216;bumped&#8217; 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&#8216;ll change that later&#8230;)
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
+ &#8216;complement(join(10..20,50..70))&#8217;. 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&#8216;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&#8216;s look at the other end: the Feature object that gets
207
+ created. In the Feature#initialize method, you&#8216;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&#8216;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&#8216;ve got a directed feature (so one with an arrow), and the
233
+ 3&#8217; end falls outside of the view. What would happen, is that the
234
+ 3&#8217; end that&#8216;s out of view would be chopped of (that&#8216;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&#8216;t want that. Instead, the arrow
237
+ should be removed.
238
+ </p>
239
+ <p>
240
+ That&#8216;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&#8216;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 &#8216;line_to&#8217;.
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: &quot;Before you can start to draw something with
280
+ cairo, you need to create the context. &lt;SNIP&gt; 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.&quot; So that&#8216;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&#8216;s walk through the code itself&#8230;
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&#8216;s a slight problem: we
293
+ can&#8216;t know the height of the picture until it&#8216;s actually drawn.
294
+ The way we&#8216;ll circumvent this, is that we create a really high
295
+ picture (called &quot;huge_panel_drawing&quot;) that we&#8216;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&#8216;d still want to see usable
303
+ ticks; and if we&#8216;ve zoomed out to a huge region, we don&#8216;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&#8216;s a small issue when you
311
+ actually start drawing the ticks. Most of the time, we don&#8216;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&#8216;ve
316
+ found that one, it&#8216;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&#8216;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&#8216;t move
337
+ it down a row at a time until there&#8216;s room for it.
338
+ </p>
339
+ <p>
340
+ So for example, suppose we&#8216;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 =&gt; [(100..150),(200..225)] }
346
+ </pre>
347
+ <p>
348
+ If we&#8216;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 =&gt; [(100..150),(200..225)],
355
+ 2 =&gt; [(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&#8216;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&#8216;s no way the arrow will be visible. If
364
+ we&#8216;d try to draw that arrow anyway, it would become bigger than the
365
+ feature itself. Another reason would be if the feature&#8216;s 3&#8217; 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>, &#8230;).
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 &quot;huge_panel_drawing&quot; 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>