Class: Bio::Graphics::Panel

Inherits:
Object
  • Object
show all
Defined in:
lib/bio/graphics/panel.rb

Overview

The Bio::Graphics::Panel class describes the complete graph and contains all tracks. See Bio::Graphics documentation for explanation of interplay between different classes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(length, opts = {}) ⇒ Panel

Create a new Bio::Graphics::Panel object

g = Bio::Graphics::Panel.new(456)

The height of the image is calculated automatically depending on how many tracks and features it contains. The width of the image defaults to 800 pt but can be set manually by using the width argument to the opts hash:

g = Bio::Graphics::Panel.new(456, :width => 1200)

See also: Bio::Graphics::Panel::Track, Bio::Graphics::Panel::Track::Feature

Arguments:

* length

length of the thing you want to visualize, e.g for visualizing a sequence that is 3.24 kb long, use 324. (required)

  • :width :: width of the resulting image in pixels. (default: 800)
  • :clickable :: whether the picture should have clickable glyphs or not (default: false) If set to true, a html file will be created with the map.
  • :display_start :: start coordinate to be displayed (default: 1)
  • :display_stop :: stop coordinate to be displayed (default: length of sequence)
  • :vertical :: Boolean: false = horizontal (= default)
  • :format :: File format of the picture. Can be :png, :svg, :pdf or :ps (default: :png)
Returns

Bio::Graphics::Panel object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/bio/graphics/panel.rb', line 110

def initialize(length, opts = {})
  @length = length
  opts = {
    :width => DEFAULT_PANEL_WIDTH,
    :display_range => Range.new(0,@length),
    :vertical => false,
    :clickable => false,
    :format => :png
  }.merge(opts)
  
  @width = opts[:width].to_i

  @display_range = opts[:display_range]
  @display_start = [0, @display_range.lend].max
  @display_stop = [@length,@display_range.rend].min
  if @display_stop <= @display_start
    raise "[ERROR] Start coordinate to be displayed has to be smaller than stop coordinate."
  end
  @display_range = Range.new(@display_start,@display_stop)
  
  @vertical = opts[:vertical]
  @clickable = opts[:clickable]
  
  @format = opts[:format]
  if ! [:png, :svg, :pdf, :ps].include?(@format)
    raise "[ERROR] Format has to be one of :png, :svg, :pdf or :ps."
  end
  
  @tracks = Array.new
  @number_of_feature_rows = 0
  @image_map = ImageMap.new

  @rescale_factor = (@display_stop - @display_start).to_f / @width
  
  # To prevent that we do the whole drawing thing multiple times
  @final_panel_destination = nil
end

Instance Attribute Details

#clickable ⇒ Object

Returns the value of attribute clickable.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def clickable
  @clickable
end

#display_range ⇒ Object

Returns the value of attribute display_range.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def display_range
  @display_range
end

#display_start ⇒ Object

Returns the value of attribute display_start.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def display_start
  @display_start
end

#display_stop ⇒ Object

Returns the value of attribute display_stop.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def display_stop
  @display_stop
end

#final_panel_destination ⇒ Object

Returns the value of attribute final_panel_destination.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def final_panel_destination
  @final_panel_destination
end

#format ⇒ Object

Returns the value of attribute format.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def format
  @format
end

#height ⇒ Object

Returns the value of attribute height.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def height
  @height
end

#image_map ⇒ Object

Returns the value of attribute image_map.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def image_map
  @image_map
end

#length ⇒ Object

Returns the value of attribute length.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def length
  @length
end

#number_of_feature_rows ⇒ Object

Returns the value of attribute number_of_feature_rows.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def number_of_feature_rows
  @number_of_feature_rows
end

#rescale_factor ⇒ Object

Returns the value of attribute rescale_factor.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def rescale_factor
  @rescale_factor
end

#tracks ⇒ Object

Returns the value of attribute tracks.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def tracks
  @tracks
end

#vertical ⇒ Object

Returns the value of attribute vertical.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def vertical
  @vertical
end

#width ⇒ Object

Returns the value of attribute width.



147
148
149
# File 'lib/bio/graphics/panel.rb', line 147

def width
  @width
end

Instance Method Details

#add_track(name, opts = {}) ⇒ Object

Adds a Bio::Graphics::Track container to this panel. A panel contains a logical grouping of features, e.g. (for sequence annotation:) genes, polymorphisms, ESTs, etc.

est_track = g.add_track('ESTs', :label => false, :glyph => :directed_generic) gene_track = g.add_track('genes', :label => true)


Arguments:

* name

Name to be displayed at the top of the track. (Required)

  • :label :: boolean. Whether or not to display the labels for the features. (Default = true)
  • :glyph :: Default glyph for features in this track. For more info, see the lib/bio/graphics/glyph directory. (Default = :generic)
  • :colour :: Default colour for features in this track, in RGB (Default = [0,0,1])
Returns

Bio::Graphics::Track object that has just been created



166
167
168
169
170
# File 'lib/bio/graphics/panel.rb', line 166

def add_track(name, opts = {})
  track = Bio::Graphics::Track.new(self, name, opts)
  @tracks.push(track)
  return track
end

#draw(file_name) ⇒ Object

Create the drawing

The fact that display_start and display_stop can be set has two consequences:

  1. not all features are drawn
  2. the x-coordinate of all glyphs has to be corrected ++


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/bio/graphics/panel.rb', line 179

def draw(file_name)
  if @final_panel_drawing.nil?
    # Create a panel that is huge vertically
    huge_height = 2000

    huge_panel_destination = nil
    huge_panel_destination = Cairo::ImageSurface.new(1, @width, huge_height)

    background = Cairo::Context.new(huge_panel_destination)
    background.set_source_rgb(1,1,1)
    background.rectangle(0,0,@width,huge_height).fill

    # Add ruler
    vertical_offset = 0
    ruler = Ruler.new(self)
    ruler.draw(huge_panel_destination)
    vertical_offset += ruler.height

    # Add tracks
    @tracks.each do |track|
      track.vertical_offset = vertical_offset
      track.draw(huge_panel_destination)
      @number_of_feature_rows += track.number_of_feature_rows
      vertical_offset += ( track.number_of_feature_rows*(FEATURE_HEIGHT+FEATURE_V_DISTANCE+5)) + 10 # '10' is for the header
    end

    # And create a smaller version of the panel
    @height = ruler.height
    @height += 20*@number_of_feature_rows
    @height += 10*@tracks.length #To correct for the track headers

    if @vertical
      @image_map.flip_orientation(@width)
      
      max_size = [@height, @width].max
      rotated_destination = Cairo::ImageSurface.new(1, max_size, max_size)
      rotated_context = Cairo::Context.new(rotated_destination)
      rotated_context.rotate(3*PI/2)
      rotated_context.translate(-@width, 0)
      rotated_context.set_source(huge_panel_destination, 0, 0)
      rotated_context.rectangle(0,0,max_size, max_size).fill

      @width, @height = @height, @width
      huge_panel_destination = rotated_destination
    end

    @final_panel_destination = Cairo::ImageSurface.new(1, @width, @height)
    resized_context = Cairo::Context.new(@final_panel_destination)
    resized_context.set_source(huge_panel_destination, 0, 0)
    resized_context.rectangle(0,0,@width, @height).fill
  end
  
  # And print to file
  if @format == :png
    @final_panel_destination.write_to_png(file_name)
  else
    case @format
    when :pdf
      output_destination = Cairo::PDFSurface.new(file_name, @width, @height)
    when :ps
      output_destination = Cairo::PSSurface.new(file_name, @width, @height)
    when :svg
      output_destination = Cairo::SVGSurface.new(file_name, @width, @height)
    end
    
    output_context = Cairo::Context.new(output_destination)
    output_context.set_source(@final_panel_destination, 0, 0)
    output_context.rectangle(0,0,@width, @height).fill
  end
  

  if @clickable # create png and map
    html_filename = file_name.sub(/\.[^.]+$/, '.html')
    html = File.open(html_filename,'w')
    html.puts "<html>"
    html.puts "<body>"
    html.puts @image_map.to_s
    html.puts "<img border='1' src='" + file_name + "' usemap='#image_map' />"
    html.puts "</body>"
    html.puts "</html>"
    html.close
  end
end