Class: Bioroebe::SVG::Page
- Inherits:
-
Object
- Object
- Bioroebe::SVG::Page
- Defined in:
- lib/bioroebe/svg/page.rb
Overview
Bioroebe::SVG::Page
Class Method Summary collapse
-
.from_json(args) ⇒ Object
# === Bioroebe::SVG::Page.from_json.
-
.parse_gff(gff_file = HOME_DIRECTORY_OF_USER_X+'DATA/PROGRAMMING_LANGUAGES/RUBY/src/bioroebe/test/test_gene.gff') ⇒ Object
# === Page.parse_gff.
Instance Method Summary collapse
-
#add_track(args) ⇒ Object
# === add_track.
-
#compute_boundaries(feature) ⇒ Object
# === compute_boundaries ========================================================================= #.
-
#draw ⇒ Object
# === draw.
-
#draw_circle(args) ⇒ Object
# === draw_circle ========================================================================= #.
-
#draw_directed(args) ⇒ Object
# === draw_directed ========================================================================= #.
-
#draw_down_triangle(args) ⇒ Object
# === draw_down_triangle ========================================================================= #.
-
#draw_features(track) ⇒ Object
# === draw_features.
-
#draw_generic(args) ⇒ Object
# === draw_generic ========================================================================= #.
-
#draw_histogram(args) ⇒ Object
# === draw_histogram ========================================================================= #.
-
#draw_label(args) ⇒ Object
# === draw_label.
-
#draw_scale ⇒ Object
# === draw_scale.
-
#draw_span(args) ⇒ Object
# === draw_span ========================================================================= #.
-
#draw_transcript(args) ⇒ Object
# === draw_transcript ========================================================================= #.
-
#draw_up_triangle(args) ⇒ Object
# === draw_up_triangle ========================================================================= #.
-
#get_limits ⇒ Object
# === get_limits.
-
#get_markup ⇒ Object
# === get_markup.
-
#initialize(i) ⇒ Page
constructor
# === initialize.
-
#reset ⇒ Object
# === reset (reset tag) ========================================================================= #.
-
#to_px(num) ⇒ Object
# === to_px.
-
#write(file) ⇒ Object
# === write (write tag).
Constructor Details
#initialize(i) ⇒ Page
#
initialize
Creates a new Page object.
Arguments:
height: this is the minimum height of the rendered page.
width: this is the minimum width of the rendered page.
background_color: this is the background color of the page
(default is none), can be any SVG colour
eg rgb(256,0,0) or #FF0000.
#
47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/bioroebe/svg/page.rb', line 47 def initialize(i) @height = i[:height] @width = i[:width] i[:style] = "background-color:#{i[:background_color]};" if i[:background_color] # ======================================================================= # # === @svg # # Instantiate a new SVGEE object next. # ======================================================================= # @svg = SVGEE.new(i) @num_intervals = i[:number_of_intervals] @svg.update_height(@height) reset end |
Class Method Details
.from_json(args) ⇒ Object
#
Bioroebe::SVG::Page.from_json
Takes a custom-written json file and uses it to generate an SVG document based on the information in that page.
-
:json a JSON file describing the parameters and files needed to build
an SVG document
#
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/bioroebe/svg/page.rb', line 88 def self.from_json(args) require 'json' data = JSON.parse(File.open(args[:json], 'r').read) p = Page.new(:width => data['Page']['width'], :height => data['Page']['height'], :number_of_intervals => data['Page']['intervals']) data['Tracks'].each { |track| # Prepare the tracks-arguments. track_args = track.dup track_args.delete('file') track_args.delete('file_type') track_args = track_args.inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo } # ===================================================================== # # Convert any of the pre-made gradient strings in the keys # to symbol. # ===================================================================== # track_args.each_key { |k| next unless track_args[k].respond_to?(:to_sym) track_args[k] = track_args[k].to_sym if Glyph.gradients.include?(track_args[k].to_sym) } svg_track = p.add_track(track_args) features = [] ##set up the features... case track['file_type'] # Deal with the gff and data files. # ===================================================================== # # === gff # ===================================================================== # when 'gff' groups = {} parentless_features = [] Page.parse_gff(track['file']).each { |gff| #gets features in a list and links their children to them as members of the array at the key parent_id = gff.attributes.select { |a| a.first == 'Parent' } if parent_id.empty? parentless_features << gff else if groups[parent_id.first.last].nil? groups[parent_id.first.last] = [] groups[parent_id.first.last] << gff else groups[parent_id.first.last] << gff end end } # =================================================================== # # Now flick through the parentless features and add any # exons or UTRs. # =================================================================== # parentless_features.each { |plf| gff_id = plf.attributes.select { |a| a.first == 'ID' } gff_id = gff_id.first.last exons = [] utrs = [] children = groups[gff_id] || children = [] children.each { |child| case child.feature when 'exon','CDS' exons += [child.start, child.end] when /utr/i # Handle UTRs here. utrs += [child.start, child.end] end } features << MiniFeature.new( :start => plf.start, :end => plf.end, :exons => exons, :utrs => utrs, :strand => plf.strand, :id => gff_id ) } # parentless features end # ===================================================================== # # === data # ===================================================================== # when 'data' # =================================================================== # # Each line is a data feature. # =================================================================== # File.open(track['file'], 'r').each { |line| start, stop, value = line.split(/\t/) features << MiniFeature.new( :start => start.to_i, :end => stop.to_i, :segment_height => value.to_f ) } end features.each { |f| svg_track.add(f) } } # track end p.write(args[:outfile]) end |
.parse_gff(gff_file = HOME_DIRECTORY_OF_USER_X+'DATA/PROGRAMMING_LANGUAGES/RUBY/src/bioroebe/test/test_gene.gff') ⇒ Object
#
Page.parse_gff
This method will parse a GFF file into an Array of Bio::GFF::GFF3::Record objects
-
gff_file - a GFF-formatted file
-
returns - an Array of Bio::GFF::GFF3::Record objects
#
353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/bioroebe/svg/page.rb', line 353 def self.parse_gff( gff_file = HOME_DIRECTORY_OF_USER_X+'DATA/PROGRAMMING_LANGUAGES/RUBY/src/bioroebe/test/test_gene.gff' ) require 'bio' # This depends on 'bio' gem for now, unortunately. a = [] File.open(gff_file).each { |line| next if line =~ /^#/ a << Bio::GFF::GFF3::Record.new(line) } a end |
Instance Method Details
#add_track(args) ⇒ Object
#
add_track
Adds a new Bioroebe::SVG::Track object to the current Bioroebe::SVG::Page object.
args
-
:glyph = one of Bioroebe::SVG::Glyphs#glyphs currently
- :generic, :directed, :transcript, :scale, :label, :histogram, :circle, :down_triangle, :up_triangle, :span
-
:stroke_color = the outline colour of the glyphs in the track (default = “black”), can be any SVG colour eg rgb(256,0,0) or #FF0000
-
:fill_color = the fill colour of the glyphs in the track (default = 'red'), can be any SVG colour eg rgb(256,0,0) or #FF0000, or one of the built in gradient types Bioroebe::SVG::Glyph#gradients
- :red_white_h, :green_white_h, :blue_white_h, :yellow_white_h, :red_white_radial, :green_white_radial, :blue_white_radial, :yellow_white_radial
-
or a custom definition of a gradient.
{:type => :radial, :id => :custom, :cx => 5, :cy => 5, :r => 50, :fx => 50, :fy => 50,
:stops => [ { :offset => 0, :color => 'rgb(255,255,255)', :opacity => 0 }, { :offset => 100, :color => 'rgb(0,127,200)', :opacity => 1 }, ]
}
-
:track_height = minimum height for the track, will be modified automatically if more space is needed e.g for overlapping features (default = auto),
-
:name = a displayed name for the track (default = 'feature_track')
-
:label = display the name given to the track (default = true),
-
:stroke_width = width in pixels of the outline of the glyphs (default=1)
-
:x_round = x radius of the ellipse used to round off the corners of rectangles (default = 1)
-
:y_round = y radius of the ellipse used to round off the corners of rectangles (default = 1)
:utr_fill_color = the fill colour of the utr part of the glyph (default = 'black'), can be any SVG colour eg rgb(256,0,0) or #FF0000, or one of the built in gradient types Bioroebe::SVG::Glyph#gradients
[:red_white_h, :green_white_h, :blue_white_h, :yellow_white_h, :red_white_radial, :green_white_radial, :blue_white_radial, :yellow_white_radial ]
or a custom definition of a gradient
{:type => :radial, :id => :custom, :cx => 5, :cy => 5, :r => 50, :fx => 50, :fy => 50,
:stops => [ { :offset => 0, :color => 'rgb(255,255,255)', :opacity => 0 }, { :offset => 100, :color => 'rgb(0,127,200)', :opacity => 1 }, ]
}
-
:utr_stroke = the outline colour of the utr part of the glyph (default = “black”), can be any SVG colour eg rgb(256,0,0) or #FF0000
-
:utr_stroke_width = The width of the outline stroke for the utr part of the glyph (default = 1)
-
:exon_fill_color = the fill colour of the utr part of the glyph (default = 'red'), can be any SVG colour eg rgb(256,0,0) or #FF0000, or one of the built in gradient types Bioroebe::SVG::Glyph#gradients or a custom definition of a gradient
- :red_white_h, :green_white_h, :blue_white_h, :yellow_white_h, :red_white_radial, :green_white_radial, :blue_white_radial, :yellow_white_radial
-
or a custom definition of a gradient {:type => :radial, :id => :custom, :cx => 5, :cy => 5, :r => 50, :fx => 50, :fy => 50,
:stops => [ { :offset => 0, :color => 'rgb(255,255,255)', :opacity => 0 }, { :offset => 100, :color => 'rgb(0,127,200)', :opacity => 1 }, ]
:exon_stroke = the outline colour of the exon part of the glyph (default = “black”) can be any SVG colour eg rgb(256,0,0) or #FF0000 :exon_stroke_width = The width of the outline stroke for the exon part
of the glyph (default = 1)
:line_color = the colour for the line part that joins the blocks (default = 'black') can be any SVG colour eg rgb(256,0,0) or #FF0000 :line_width = the width ffor the line part that joins the blocks (default = 1) :exon_style = an arbitrary SVG compliant style string eg “fill-opacity:0.4;” :utr_style = an arbitrary SVG compliant style string eg “fill-opacity:0.4;” :line_style = an arbitrary SVG compliant style string eg “fill-opacity:0.4;” :gap_marker = style of the line between blocks - either angled or straight
Will return:
a new Bioroebe::SVG::Track object
#
-
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/bioroebe/svg/page.rb', line 277 def add_track(args) # ======================================================================= # # Sort out the colour/gradient options # ======================================================================= # [:fill_color, :exon_fill_color, :utr_fill_color].each { |colour_tag| if Glyph.gradients.include?(args[colour_tag]) @svg.gradient(Glyph.gradient(args[colour_tag])) args[colour_tag] = "url(##{args[colour_tag]})" elsif args[colour_tag].instance_of?(Hash) @svg.gradient(args[colour_tag]) args[colour_tag] = "url(##{args[colour_tag][:id]})" end } @tracks << Track.new(args) return @tracks.last end |
#compute_boundaries(feature) ⇒ Object
#
compute_boundaries
#
327 328 329 330 331 |
# File 'lib/bioroebe/svg/page.rb', line 327 def compute_boundaries(feature) feat_end = feature.end feat_end += (8 * @nt_per_px_x * feature.id.to_s.length).to_i if feature.id and @nt_per_px_x [feature.start, feat_end] end |
#draw ⇒ Object
#
draw
Prints the svg text to STDOUT. You can capture this and redirect it into a file.
#
557 558 559 |
# File 'lib/bioroebe/svg/page.rb', line 557 def draw puts get_markup end |
#draw_circle(args) ⇒ Object
#
draw_circle
#
394 395 396 |
# File 'lib/bioroebe/svg/page.rb', line 394 def draw_circle(args) Glyph.circle(args).each { |g| @svg.add_primitive(g) } end |
#draw_directed(args) ⇒ Object
#
draw_directed
#
387 388 389 |
# File 'lib/bioroebe/svg/page.rb', line 387 def draw_directed(args) Glyph.directed(args).each { |g| @svg.add_primitive(g) } end |
#draw_down_triangle(args) ⇒ Object
#
draw_down_triangle
#
422 423 424 |
# File 'lib/bioroebe/svg/page.rb', line 422 def draw_down_triangle(args) Glyph.down_triangle(args).each { |g| @svg.add_primitive(g) } end |
#draw_features(track) ⇒ Object
#
draw_features
Takes a Bioroebe::SVG::Track object and does the work to draw features.
It examines the the type of track and calculates the required parameters * args
- an Array of Bioroebe::SVG::Track object
#
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/bioroebe/svg/page.rb', line 443 def draw_features(track) if [:histogram, 'histogram'].include?(track.glyph) #do different stuff for data tracks... y = @track_top + (track.track_height) max = track.max_y ? track.max_y : track.features.sort { |a, b| a.segment_height <=> b.segment_height }.last.segment_height min = 0 if track.label draw_label(:text => track.name, :y => @track_top += 30, :x => 3) end draw_label(:text => max, :x => to_px(@scale_stop - @scale_start) + 5, :y => @track_top + 5) draw_label(:text => min, :x => to_px(@scale_stop - @scale_start) + 5, :y => @track_top + track.track_height + 5) data_interval = max - min data_per_px = track.track_height.to_f / data_interval.to_f track.features.each do |f| x = to_px(f.start - @scale_start) width = to_px((f.end - @scale_start) - (f.start - @scale_start)) height = f.segment_height.to_f * data_per_px y = @track_top + track.track_height - height + 5 #$stderr.puts f.segment_height, data_per_px, data_interval, max, min, "------" self.send("draw_#{track.glyph}", {:x => x, :y => y, :width => width, :height => height}.merge!(track.args)) end @track_top += (track.track_height) + 20 else ##following stuff for the features if track.label draw_label(:text => track.name, :y => @track_top += 30, :x => 3) end track.get_rows(self) ##work out how many rows and which features belong in each row... track.features.each_with_index do |f, index| x = to_px(f.start - @scale_start) #bottom left of feature all_sub_blocks = [] #convert the exon and utr start stops to px start stops and px widths exons = [] if f.exons f.exons.each_slice(2).each { |exon| all_sub_blocks << exon next if exon.nil? exons << [to_px(exon[0] - @scale_start), to_px((exon[1] - @scale_start) - (exon[0] - @scale_start))] } end f.exons = exons utrs = [] if f.utrs f.utrs.each_slice(2).each { |utr| all_sub_blocks << utr next if utr.nil? utrs << [to_px(utr[0] - @scale_start), to_px((utr[1] - @scale_start) - (utr[0] - @scale_start))] } end f.utrs = utrs # If there are any intron like gaps.. get where they would be. if not all_sub_blocks.empty? all_sub_blocks = all_sub_blocks.sort { |a, b| a.first <=> b.first } all_sub_blocks.each_index do |i| next if i + 1 == all_sub_blocks.length or all_sub_blocks[i].last >= all_sub_blocks[i + 1].first #skip if there is no gap f.block_gaps << [to_px(all_sub_blocks[i].last - @scale_start), to_px((all_sub_blocks[i + 1].first - @scale_start) - (all_sub_blocks[i].last - @scale_start))] end end width = to_px((f.end - @scale_start) - (f.start - @scale_start)) if track.min_width and width < track.min_width width = track.min_width end y = @track_top + (track.feature_rows[index] * 2 * track.feature_height) self.send("draw_#{track.glyph}", {:x => x, :y => y, :width => width, :strand => f.strand, :exons => f.exons, :utrs => f.utrs, :block_gaps => f.block_gaps, :height => track.feature_height, :params => f.params }.merge!(track.args)) if f.id draw_label(:y => y, :x => x+width+2, :text => f.id) end end @track_top += (track.feature_height * track.number_rows * 2) + 20 end @height = @track_top + 100 # Fudge. @svg.update_height(@height) # @svg.update_width(@width + 200) end |
#draw_generic(args) ⇒ Object
#
draw_generic
#
380 381 382 |
# File 'lib/bioroebe/svg/page.rb', line 380 def draw_generic(args) #remember presentation info comes from [email protected] when the track is defined Glyph.generic(args).each { |g| @svg.add_primitive(g) } end |
#draw_histogram(args) ⇒ Object
#
draw_histogram
#
408 409 410 |
# File 'lib/bioroebe/svg/page.rb', line 408 def draw_histogram(args) Glyph.generic(args).each { |g| @svg.add_primitive(g) } end |
#draw_label(args) ⇒ Object
#
draw_label
Adds the Bioroebe::SVG::Primitive objects to the SVGEE object
-
args
- an Array of Bioroebe::SVG::Primitive object
#
371 372 373 374 375 |
# File 'lib/bioroebe/svg/page.rb', line 371 def draw_label(args) Glyph.label(:text => args[:text], :x => args[:x], :y => args[:y]).each { |g| @svg.add_primitive(g) } end |
#draw_scale ⇒ Object
#
draw_scale
Adds scale bar to the list of objects to be rendered in the final.
#
338 339 340 341 342 343 |
# File 'lib/bioroebe/svg/page.rb', line 338 def draw_scale Glyph.scale(:start => @scale_start, :stop => @scale_stop, :number_of_intervals => @num_intervals, :page_width => @width).each { |entry| @svg.add_primitive(entry) } end |
#draw_span(args) ⇒ Object
#
draw_span
#
429 430 431 432 433 |
# File 'lib/bioroebe/svg/page.rb', line 429 def draw_span(args) Glyph.span(args).each { |g| @svg.add_primitive(g) } end |
#draw_transcript(args) ⇒ Object
#
draw_transcript
#
401 402 403 |
# File 'lib/bioroebe/svg/page.rb', line 401 def draw_transcript(args) Glyph.transcript(args).each { |g| @svg.add_primitive(g) } end |
#draw_up_triangle(args) ⇒ Object
#
draw_up_triangle
#
415 416 417 |
# File 'lib/bioroebe/svg/page.rb', line 415 def draw_up_triangle(args) Glyph.up_triangle(args).each { |g| @svg.add_primitive(g) } end |
#get_limits ⇒ Object
#
get_limits
Calculates the Page scale-start and scale-stop position and the nucleotides per pixel for the current Page.
#
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/bioroebe/svg/page.rb', line 300 def get_limits @tracks.each { |track| lowest = track.features.sort { |x, y| x.start <=> y.start }.first.start highest = track.features.sort { |x, y| y.end <=> x.end }.first.end @scale_start = lowest if lowest < @scale_start @scale_stop = highest if highest > @scale_stop @nt_per_px_x = (@scale_stop - @scale_start).to_f / @width.to_f } begin old_nt_per_px_x = @nt_per_px_x @tracks.each { |track| highest = track.features.map { |feat| compute_boundaries(feat)[1] }.max if highest > @scale_stop @scale_stop = highest @nt_per_px_x = (@scale_stop - @scale_start).to_f / @width.to_f end } end while (@nt_per_px_x - old_nt_per_px_x).abs > 1 end |
#get_markup ⇒ Object
#
get_markup
Generates the SVG text.
#
542 543 544 545 546 547 548 549 |
# File 'lib/bioroebe/svg/page.rb', line 542 def get_markup get_limits draw_scale @tracks.each { |track| draw_features(track) } @svg.draw end |
#reset ⇒ Object
#
reset (reset tag)
#
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/bioroebe/svg/page.rb', line 65 def reset # ======================================================================= # # === @track_top # ======================================================================= # @track_top = 30 # ======================================================================= # # === @tracks # ======================================================================= # @tracks = [] # Array of track objects with loads of features in it. @scale_start = 1.0/0.0 @scale_stop = -1.0/0.0 @nt_per_percent = 1 end |
#to_px(num) ⇒ Object
#
to_px
Calculates the pixel value for a given number.
#
533 534 535 |
# File 'lib/bioroebe/svg/page.rb', line 533 def to_px(num) (num.to_f / @nt_per_px_x.to_f) end |
#write(file) ⇒ Object
#
write (write tag)
Writes the SVG text to a file
#
566 567 568 |
# File 'lib/bioroebe/svg/page.rb', line 566 def write(file) File.open(file, 'w').write(get_markup) end |