bio-graphics 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/bio-graphics.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# = bio-graphics.rb - Loading all Bio::Graphics modules
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (C) 2007
|
5
|
+
# Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
6
|
+
# License:: The Ruby License
|
7
|
+
#
|
8
|
+
begin
|
9
|
+
require 'bio'
|
10
|
+
require 'cairo'
|
11
|
+
rescue nil
|
12
|
+
end
|
13
|
+
|
14
|
+
require File.dirname(__FILE__) + '/bio/graphics/image_map.rb'
|
15
|
+
require File.dirname(__FILE__) + '/bio/graphics/panel.rb'
|
16
|
+
require File.dirname(__FILE__) + '/bio/graphics/track.rb'
|
17
|
+
require File.dirname(__FILE__) + '/bio/graphics/feature.rb'
|
18
|
+
require File.dirname(__FILE__) + '/bio/graphics/ruler.rb'
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#
|
2
|
+
# = bio/graphics/feature.rb - feature class
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (C) 2007
|
5
|
+
# Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
6
|
+
# License:: The Ruby License
|
7
|
+
#
|
8
|
+
module Bio
|
9
|
+
module Graphics
|
10
|
+
class Panel
|
11
|
+
class Track
|
12
|
+
# The Bio::Graphics::Track::Feature class describes features to be
|
13
|
+
# placed on the graph. See Bio::Graphics documentation for explanation
|
14
|
+
# of interplay between different classes.
|
15
|
+
#
|
16
|
+
# The position of the Feature is a Bio::Locations object to make it possible
|
17
|
+
# to transparently work with simple and spliced features.
|
18
|
+
class Feature
|
19
|
+
# !!Not to be used directly. Use
|
20
|
+
# Bio::Graphics::Panel::Track.add_feature instead!!
|
21
|
+
# A feature can not exist except within the confines of a
|
22
|
+
# Bio::Graphics::Panel::Track object.
|
23
|
+
#
|
24
|
+
#--
|
25
|
+
# This is necessary because the feature needs to know the colour and glyph,
|
26
|
+
# both of which are defined within the panel.
|
27
|
+
#++
|
28
|
+
#
|
29
|
+
# ---
|
30
|
+
# *Arguments*:
|
31
|
+
# * _panel_ (required) :: Bio::Graphics::Panel::Track object that this
|
32
|
+
# feature belongs to
|
33
|
+
# * _name_ (required) :: Name of the feature
|
34
|
+
# * _location_ :: Bio::Locations object. Default = whole panel, forward strand
|
35
|
+
# * _link_ :: URL for clickable images
|
36
|
+
# *Returns*:: Bio::Graphics::Track::Feature object
|
37
|
+
def initialize(track, name, location = Bio::Locations.new('1..' + track.panel.length.to_s), link = nil)
|
38
|
+
@track = track
|
39
|
+
@name = name
|
40
|
+
@location = location
|
41
|
+
@start = location.collect{|l| l.from}.min.to_i
|
42
|
+
@stop = location.collect{|l| l.to}.max.to_i
|
43
|
+
@strand = location[0].strand.to_i
|
44
|
+
@link = link
|
45
|
+
@pixel_range_collection = Array.new
|
46
|
+
@chopped_at_start = false
|
47
|
+
@chopped_at_stop = false
|
48
|
+
@hidden_subfeatures_at_start = false
|
49
|
+
@hidden_subfeatures_at_stop = false
|
50
|
+
|
51
|
+
# Get all pixel ranges for the subfeatures
|
52
|
+
location.each do |l|
|
53
|
+
# xxxxxx [ ]
|
54
|
+
if l.to < track.panel.display_start
|
55
|
+
@hidden_subfeatures_at_start = true
|
56
|
+
next
|
57
|
+
# [ ] xxxxx
|
58
|
+
elsif l.from > track.panel.display_stop
|
59
|
+
@hidden_subfeatures_at_stop = true
|
60
|
+
next
|
61
|
+
# xxxx[xxx ]
|
62
|
+
elsif l.from < track.panel.display_start and l.to > track.panel.display_start
|
63
|
+
start_pixel = 1
|
64
|
+
stop_pixel = ( l.to - track.panel.display_start ).to_f / track.panel.rescale_factor
|
65
|
+
@chopped_at_start = true
|
66
|
+
# [ xxxx]xxxx
|
67
|
+
elsif l.from < track.panel.display_stop and l.to > track.panel.display_stop
|
68
|
+
start_pixel = ( l.from - track.panel.display_start ).to_f / track.panel.rescale_factor
|
69
|
+
stop_pixel = track.panel.width
|
70
|
+
@chopped_at_stop = true
|
71
|
+
# xxxx[xxxxxxxxxx]xxxx
|
72
|
+
elsif l.from < track.panel.display_start and l.to > track.panel.display_stop
|
73
|
+
start_pixel = 1
|
74
|
+
stop_pixel = track.panel.width
|
75
|
+
@chopped_at_start = true
|
76
|
+
@chopped_at_stop = true
|
77
|
+
# [ xxxxx ]
|
78
|
+
else
|
79
|
+
start_pixel = ( l.from - track.panel.display_start ).to_f / track.panel.rescale_factor
|
80
|
+
stop_pixel = ( l.to - track.panel.display_start ).to_f / track.panel.rescale_factor
|
81
|
+
end
|
82
|
+
|
83
|
+
@pixel_range_collection.push(PixelRange.new(start_pixel, stop_pixel))
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# The track that this feature belongs to
|
89
|
+
attr_accessor :track
|
90
|
+
|
91
|
+
# The name of the feature
|
92
|
+
attr_accessor :name
|
93
|
+
|
94
|
+
# The location of the feature (which is a Bio::Locations object)
|
95
|
+
attr_accessor :location
|
96
|
+
|
97
|
+
# The start position of the feature (in bp)
|
98
|
+
attr_accessor :start
|
99
|
+
|
100
|
+
# The stop position of the feature (in bp)
|
101
|
+
attr_accessor :stop
|
102
|
+
|
103
|
+
# The strand of the feature
|
104
|
+
attr_accessor :strand
|
105
|
+
|
106
|
+
# The URL to be followed when the glyph for this feature is clicked
|
107
|
+
attr_accessor :link
|
108
|
+
|
109
|
+
# The array keeping the pixel ranges for the sub-features. Unspliced
|
110
|
+
# features will just have one element, while spliced features will
|
111
|
+
# have more than one.
|
112
|
+
attr_accessor :pixel_range_collection
|
113
|
+
|
114
|
+
# Is the first subfeature incomplete?
|
115
|
+
attr_accessor :chopped_at_start
|
116
|
+
|
117
|
+
# Is the last subfeature incomplete?
|
118
|
+
attr_accessor :chopped_at_stop
|
119
|
+
|
120
|
+
# Are there subfeatures out of view at the left side of the picture?
|
121
|
+
attr_accessor :hidden_subfeatures_at_start
|
122
|
+
|
123
|
+
# Are there subfeatures out of view at the right side of the picture?
|
124
|
+
attr_accessor :hidden_subfeatures_at_stop
|
125
|
+
|
126
|
+
class PixelRange
|
127
|
+
def initialize(start_pixel, stop_pixel)
|
128
|
+
@start_pixel, @stop_pixel = start_pixel, stop_pixel
|
129
|
+
end
|
130
|
+
attr_accessor :start_pixel, :stop_pixel
|
131
|
+
end
|
132
|
+
end #Feature
|
133
|
+
end #Track
|
134
|
+
end #Panel
|
135
|
+
end #Graphics
|
136
|
+
end #Bio
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# = bio/graphics/image_map.rb - create the image map for clickable images
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (C) 2007
|
5
|
+
# Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
6
|
+
# License:: Ruby's
|
7
|
+
class ImageMap
|
8
|
+
def initialize
|
9
|
+
@elements = Array.new
|
10
|
+
end
|
11
|
+
attr_accessor :elements
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
output = Array.new
|
15
|
+
output.push('<map name="image_map" border="1">')
|
16
|
+
@elements.each do |e|
|
17
|
+
output.push(e.to_s)
|
18
|
+
end
|
19
|
+
output.push('</map>')
|
20
|
+
return output.join("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
class ImageMapElement
|
25
|
+
def initialize(left, top, right, bottom, url = nil)
|
26
|
+
@left, @top, @right, @bottom = left, top, right, bottom
|
27
|
+
@url = ( url.nil? ) ? '' : url
|
28
|
+
end
|
29
|
+
attr_accessor :left, :top, :right, :bottom, :url
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
unless @url == ''
|
33
|
+
return '<area shape="rect" coords="' + @left.to_s + ' ' + @top.to_s + ' ' + @right.to_s + ' ' + @bottom.to_s + '" href="' + @url + '"/>'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#
|
2
|
+
# = bio/graphics/panel - panel class
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (C) 2007
|
5
|
+
# Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
6
|
+
# License:: The Ruby License
|
7
|
+
#
|
8
|
+
module Bio
|
9
|
+
# = DESCRIPTION
|
10
|
+
# The Bio::Graphics set of objects allow for creating simple images that
|
11
|
+
# display features on a linear map. A picture consists of:
|
12
|
+
# * one *panel*: container of all tracks
|
13
|
+
# * one or more *tracks*: container of the features. Multiple tracks
|
14
|
+
# can exist in the same graphic to allow for differential visualization of
|
15
|
+
# different feature types (e.g. genes as blue rectangles and polymorphisms
|
16
|
+
# as red triangles)
|
17
|
+
# * one or more *features* in each track: these are the actual features that
|
18
|
+
# you want to display (e.g. 'gene 1', 'SNP 123445')
|
19
|
+
# * a *ruler* on top of the panel: is added automatically
|
20
|
+
#
|
21
|
+
# Schematically:
|
22
|
+
# panel
|
23
|
+
# +-> track 1
|
24
|
+
# | +-> feature 1
|
25
|
+
# | +-> feature 2
|
26
|
+
# | +-> feature 3
|
27
|
+
# +-> track 2
|
28
|
+
# | +-> feature 4
|
29
|
+
# | +-> feature 5
|
30
|
+
# +-> ruler
|
31
|
+
#
|
32
|
+
# = USAGE
|
33
|
+
# # Create a panel for something with a length of 653. This could be a
|
34
|
+
# # sequence of 653 bp, but also a genetic map of 653 cM.
|
35
|
+
# g = Bio::Graphics::Panel.new(653)
|
36
|
+
#
|
37
|
+
# # Add the first track (e.g. 'genes')
|
38
|
+
# track1 = g.add_track('genes')
|
39
|
+
#
|
40
|
+
# # And put features in that track
|
41
|
+
# track1.add_feature('gene1',250,375)
|
42
|
+
# track1.add_feature('gene2',54,124)
|
43
|
+
# track1.add_feature('gene3',100,500)
|
44
|
+
#
|
45
|
+
# # Add a second track (e.g. 'polymorphisms')
|
46
|
+
# track2 = g.add_track('polymorphisms','red','triangle')
|
47
|
+
#
|
48
|
+
# # And put features on this one
|
49
|
+
# track2.add_feature('polymorphism 1',56,56)
|
50
|
+
# track2.add_feature('polymorphism 2',103,103)
|
51
|
+
#
|
52
|
+
# # Create the actual image as SVG text
|
53
|
+
# g.draw('my_picture.png')
|
54
|
+
#
|
55
|
+
# = FUTURE PROSPECTS
|
56
|
+
# Any help from other developers is welcomed to work on these features:
|
57
|
+
# * Would be nice if this module would be easily accessible from any object
|
58
|
+
# that implements bioruby's Bio::Map::ActsAsMap.
|
59
|
+
#
|
60
|
+
module Graphics
|
61
|
+
|
62
|
+
# The defaults
|
63
|
+
DEFAULT_PANEL_WIDTH = 800 # How many pixels wide do we want the picture to be?
|
64
|
+
TRACK_HEADER_HEIGHT = 12 # The track header will contain the title.
|
65
|
+
FEATURE_HEIGHT = 10 # The height in pixels of a glyph.
|
66
|
+
FEATURE_V_DISTANCE = 5 # The vertical distance in pixels between glyphs
|
67
|
+
FEATURE_ARROW_LENGTH = 5 # In pixels again.
|
68
|
+
RULER_TEXT_HEIGHT = 10 # And again...
|
69
|
+
RULER_MIN_DISTANCE_TICKS_PIXEL = 5 # There should be at least 5 pixels between
|
70
|
+
# consecutive ticks. This is used for the
|
71
|
+
# calculation of tick distance.
|
72
|
+
|
73
|
+
# The Bio::Graphics::Panel class describes the complete graph and contains
|
74
|
+
# all tracks. See Bio::Graphics documentation for explanation of interplay
|
75
|
+
# between different classes.
|
76
|
+
class Panel
|
77
|
+
# Create a new Bio::Graphics::Panel object
|
78
|
+
#
|
79
|
+
# g = Bio::Graphics::Panel.new(456)
|
80
|
+
#
|
81
|
+
# The height of the image is calculated automatically depending on how many
|
82
|
+
# tracks and features it contains. The width of the image defaults to 800 pt
|
83
|
+
# but can be set manually by using a second argument:
|
84
|
+
#
|
85
|
+
# g = Bio::Graphics::Panel.new(456, 400)
|
86
|
+
#
|
87
|
+
#
|
88
|
+
# See also: Bio::Graphics::Track, BioExt::Graphics::Feature
|
89
|
+
# ---
|
90
|
+
# *Arguments*:
|
91
|
+
# * _length_ :: length of the thing you want to visualize, e.g for
|
92
|
+
# visualizing a sequence that is 3.24 kb long, use 324.
|
93
|
+
# * _width_ :: width of the resulting image in pt. This should be a string
|
94
|
+
# and not an integer. Default = '800' (Notice the quotes...).
|
95
|
+
# * _clickable_ :: whether the picture should have clickable glyphs or not
|
96
|
+
# (default: false) If set to true, a html file will be created with
|
97
|
+
# the map.
|
98
|
+
# * _display_start_ :: start coordinate to be displayed (default: 1)
|
99
|
+
# * _display_stop_ :: stop coordinate to be displayed (default: length of sequence)
|
100
|
+
# *Returns*:: Bio::Graphics::Panel object
|
101
|
+
def initialize(length, width = DEFAULT_PANEL_WIDTH, clickable = false, display_start = nil, display_stop = nil)
|
102
|
+
@length = length.to_i
|
103
|
+
@width = width.to_i
|
104
|
+
@tracks = Array.new
|
105
|
+
@number_of_times_bumped = 0
|
106
|
+
@clickable = clickable
|
107
|
+
@image_map = ( clickable ) ? ImageMap.new : nil
|
108
|
+
@display_start = ( display_start.nil? ) ? 0 : display_start
|
109
|
+
@display_stop = ( display_stop.nil? ) ? @length : display_stop
|
110
|
+
if @display_stop <= @display_start
|
111
|
+
raise "[ERROR] Start coordinate to be displayed has to be smaller than stop coordinate."
|
112
|
+
end
|
113
|
+
@rescale_factor = (@display_stop - @display_start).to_f / @width
|
114
|
+
end
|
115
|
+
attr_accessor :length, :width, :height, :rescale_factor, :tracks, :number_of_times_bumped, :clickable, :image_map, :display_start, :display_stop
|
116
|
+
|
117
|
+
# Adds a Bio::Graphics::Track container to this panel. A panel contains a
|
118
|
+
# logical grouping of features, e.g. (for sequence annotation:) genes,
|
119
|
+
# polymorphisms, ESTs, etc.
|
120
|
+
#
|
121
|
+
# est_track = g.add_track('ESTs')
|
122
|
+
# gene_track = g.add_track('genes')
|
123
|
+
#
|
124
|
+
# ---
|
125
|
+
# *Arguments*:
|
126
|
+
# * _name_ (required) :: Name of the track to be displayed (e.g. 'genes')
|
127
|
+
# * _colour_ :: Colour to be used to draw the features within the track.
|
128
|
+
# Default = 'blue'
|
129
|
+
# * _glyph_ :: Glyph to use for drawing the features. Options are:
|
130
|
+
# 'generic', 'directed_generic', 'spliced', 'directed_spliced' and
|
131
|
+
# 'triangle'. Triangles can be used
|
132
|
+
# for features whose start and stop positions are the same (e.g. SNPs).
|
133
|
+
# If you try to draw a feature that is longer with triangles, an error
|
134
|
+
# will be shown.
|
135
|
+
# *Returns*:: Bio::Graphics::Track object that has just been created
|
136
|
+
def add_track(name, feature_colour = [0,0,1], feature_glyph = 'generic')
|
137
|
+
@tracks.push(Bio::Graphics::Panel::Track.new(self, name, feature_colour, feature_glyph))
|
138
|
+
return @tracks[-1]
|
139
|
+
end
|
140
|
+
|
141
|
+
# Create the drawing
|
142
|
+
#--
|
143
|
+
# The fact that display_start and display_stop can be set has two
|
144
|
+
# consequences:
|
145
|
+
# 1. not all features are drawn
|
146
|
+
# 2. the x-coordinate of all glyphs has to be corrected
|
147
|
+
#++
|
148
|
+
def draw(file_name)
|
149
|
+
# Create a panel that is huge vertically
|
150
|
+
huge_height = 2000
|
151
|
+
|
152
|
+
huge_panel_drawing = nil
|
153
|
+
huge_panel_drawing = Cairo::ImageSurface.new(1, @width, huge_height)
|
154
|
+
|
155
|
+
background = Cairo::Context.new(huge_panel_drawing)
|
156
|
+
background.set_source_rgb(1,1,1)
|
157
|
+
background.rectangle(0,0,@width,huge_height).fill
|
158
|
+
|
159
|
+
# Add ruler
|
160
|
+
vertical_offset = 0
|
161
|
+
ruler = Bio::Graphics::Panel::Ruler.new(self)
|
162
|
+
ruler.draw(huge_panel_drawing, vertical_offset)
|
163
|
+
vertical_offset += ruler.height
|
164
|
+
|
165
|
+
# Add tracks
|
166
|
+
@tracks.each do |track|
|
167
|
+
track.draw(huge_panel_drawing, vertical_offset)
|
168
|
+
@number_of_times_bumped += track.number_of_times_bumped
|
169
|
+
vertical_offset += ( track.number_of_times_bumped*(FEATURE_HEIGHT+FEATURE_V_DISTANCE+5)) + 10 # '10' is for the header
|
170
|
+
end
|
171
|
+
|
172
|
+
# And create a smaller version of the panel
|
173
|
+
height = ruler.height
|
174
|
+
@number_of_times_bumped.times do
|
175
|
+
height += 20
|
176
|
+
end
|
177
|
+
@tracks.length.times do #To correct for the track headers
|
178
|
+
height += 10
|
179
|
+
end
|
180
|
+
|
181
|
+
resized_panel_drawing = nil
|
182
|
+
resized_panel_drawing = Cairo::ImageSurface.new(1, @width, height)
|
183
|
+
resizing_context = Cairo::Context.new(resized_panel_drawing)
|
184
|
+
resizing_context.set_source(huge_panel_drawing, 0,0)
|
185
|
+
resizing_context.rectangle(0,0,@width, height).fill
|
186
|
+
|
187
|
+
# And print to file
|
188
|
+
resized_panel_drawing.write_to_png(file_name)
|
189
|
+
if @clickable # create png and map
|
190
|
+
html_filename = file_name.sub(/\.[^.]+$/, '.html')
|
191
|
+
html = File.open(html_filename,'w')
|
192
|
+
html.puts "<html>"
|
193
|
+
html.puts "<body>"
|
194
|
+
html.puts @image_map.to_s
|
195
|
+
html.puts "<img border='1' src='" + file_name + "' usemap='#image_map' />"
|
196
|
+
html.puts "</body>"
|
197
|
+
html.puts "</html>"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
end #Panel
|
204
|
+
end #Graphics
|
205
|
+
end #Bio
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#
|
2
|
+
# = bio/graphics/ruler - ruler class
|
3
|
+
#
|
4
|
+
# Copyright:: Copyright (C) 2007
|
5
|
+
# Jan Aerts <jan.aerts@bbsrc.ac.uk>
|
6
|
+
# License:: The Ruby License
|
7
|
+
#
|
8
|
+
module Bio
|
9
|
+
module Graphics
|
10
|
+
class Panel
|
11
|
+
# The Bio::Graphics::Ruler class describes the ruler to be drawn on the
|
12
|
+
# graph. This is created automatically when creating the picture by using
|
13
|
+
# Bio::Graphics::Panel.to_svg. See BioExt::Graphics documentation for
|
14
|
+
# explanation of interplay between different classes.
|
15
|
+
#--
|
16
|
+
# TODO: the ruler might be implemented as a special case of a track, so
|
17
|
+
# it would inherit from it (class Ruler < Bio::Graphics::Panel::Track).
|
18
|
+
# But I haven't really thought this through yet.
|
19
|
+
#++
|
20
|
+
class Ruler
|
21
|
+
# Creates a new Bio::Graphics::Panel::Ruler object.
|
22
|
+
# ---
|
23
|
+
# *Arguments*:
|
24
|
+
# * _panel_ (required) :: Bio::Graphics::Panel object that this ruler
|
25
|
+
# belongs to
|
26
|
+
# * _colour_ :: colour of the ruler. Default = 'black'
|
27
|
+
# *Returns*:: Bio::Graphics::Ruler object
|
28
|
+
def initialize(panel, colour = [0,0,0])
|
29
|
+
@panel = panel
|
30
|
+
@name = 'ruler'
|
31
|
+
@colour = colour
|
32
|
+
end
|
33
|
+
attr_accessor :panel, :name, :colour, :height, :minor_tick_distance, :major_tick_distance
|
34
|
+
|
35
|
+
def calculate_tick_distance
|
36
|
+
min_tick_distance_requirement_met = false
|
37
|
+
self.minor_tick_distance = 1 # in basepairs.
|
38
|
+
while ! min_tick_distance_requirement_met
|
39
|
+
if self.minor_tick_distance/panel.rescale_factor >= RULER_MIN_DISTANCE_TICKS_PIXEL
|
40
|
+
min_tick_distance_requirement_met = true
|
41
|
+
else
|
42
|
+
self.minor_tick_distance = self.minor_tick_distance*5
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
self.major_tick_distance = self.minor_tick_distance * 10
|
47
|
+
end
|
48
|
+
|
49
|
+
def draw(panel_drawing, vertical_offset)
|
50
|
+
ruler_drawing = Cairo::Context.new(panel_drawing)
|
51
|
+
|
52
|
+
self.calculate_tick_distance
|
53
|
+
|
54
|
+
# Draw line
|
55
|
+
ruler_drawing.move_to(0,10)
|
56
|
+
ruler_drawing.line_to(panel.width, 10)
|
57
|
+
ruler_drawing.stroke
|
58
|
+
|
59
|
+
# Draw ticks
|
60
|
+
# * Find position of first tick.
|
61
|
+
# Most of the time, we don't want the first tick on the very first
|
62
|
+
# basepair of the view. Suppose that would be position 333 in the
|
63
|
+
# sequence. Then the numbers under the major tickmarks would be:
|
64
|
+
# 343, 353, 363, 373 and so on. Instead, we want 350, 360, 370, 380.
|
65
|
+
# So we want to find the position of the first tick.
|
66
|
+
first_tick_position = panel.display_start
|
67
|
+
while first_tick_position.modulo(minor_tick_distance) != 0
|
68
|
+
first_tick_position += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# * And start drawing the rest.
|
72
|
+
first_tick_position.step(panel.display_stop, minor_tick_distance) do |tick|
|
73
|
+
tick_pixel_position = (tick - panel.display_start) / panel.rescale_factor
|
74
|
+
ruler_drawing.move_to(tick_pixel_position.floor, 5)
|
75
|
+
if tick.modulo(major_tick_distance) == 0
|
76
|
+
ruler_drawing.rel_line_to(0, 15)
|
77
|
+
|
78
|
+
# Draw tick number
|
79
|
+
ruler_drawing.select_font_face('Georgia', 1, 1)
|
80
|
+
ruler_drawing.set_font_size(RULER_TEXT_HEIGHT)
|
81
|
+
ruler_drawing.move_to(tick_pixel_position.floor, 20 + RULER_TEXT_HEIGHT)
|
82
|
+
ruler_drawing.show_text(tick.to_i.to_s)
|
83
|
+
else
|
84
|
+
ruler_drawing.rel_line_to(0, 5)
|
85
|
+
|
86
|
+
end
|
87
|
+
ruler_drawing.stroke
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
@height = 25 + RULER_TEXT_HEIGHT
|
92
|
+
end
|
93
|
+
end #Ruler
|
94
|
+
end #Panel
|
95
|
+
end #Graphics
|
96
|
+
end #Bio
|