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
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
|