Skip to content

Instantly share code, notes, and snippets.

@antunderwood
Created October 13, 2009 15:55
Show Gist options
  • Save antunderwood/209308 to your computer and use it in GitHub Desktop.
Save antunderwood/209308 to your computer and use it in GitHub Desktop.
crowd server action
# Splits up alignemnt into block sized chunks and then render them as html
class RenderAlignment < CloudCrowd::Action
require 'rubygems'
require 'bio'
# Split up alignment
def split
fasta_sequences = Bio::FlatFile.open(input_path).to_a
alignment = Bio::Alignment.new(fasta_sequences)
block_size = options['block_size']
number_of_blocks = (alignment.alignment_length/block_size.to_f).ceil
(1..number_of_blocks).each do |block_number|
start_of_slice = (block_number-1)*block_size
end_of_slice = (block_number*block_size)-1
alignment_slice = alignment.alignment_slice(start_of_slice..end_of_slice)
slicefile = File.new("alignslice-#{block_number}.fas", "w")
slicefile.write(alignment_slice.output_fasta)
slicefile.close
end
alignment_files = Dir["alignslice-*"].map {|slice| save(slice) }
alignment_files.to_json
end
# Convert an alignment into html
def process
# read in alignment
fasta_sequences = Bio::FlatFile.open(input_path).to_a
alignment = Bio::Alignment.new(fasta_sequences)
alignment.alignment_length
input_path.match(/alignslice-(\d+)\.fas$/)
block_number = $1.to_i
process_options = {'consensus_threshold' => 0.7 ,'block_size' => 81, 'highlight_colour' => "#6666FF", 'draw_ruler' => true, 'translate' => false , 'consensus' => false}.me
rge(options)
# find maximum sequence
max_name_length = (alignment.sequence_names.collect{|sequence_name| sequence_name.length}).max
sequence_names = alignment.sequence_names.collect{|sequence_name| sprintf("%#{max_name_length}s", sequence_name)}
sequence_names.collect!{|sequence_name| sequence_name.gsub(/\s/, "&nbsp;") + "&nbsp;"}
html_string =""
# generate consensus sequence string
consensus = alignment.consensus_string(process_options['consensus_threshold'])
if process_options['consensus']
html_string << sprintf("%#{max_name_length}s", "consensus").gsub(/\s/, "&nbsp;") + "&nbsp;"
html_string << consensus
html_string << "<br/>"
end
# print out sequences
sequences = alignment.alignment_collect{|sequence| sequence}
sequences.each_with_index do |sequence, index|
#set consensus match to false
consensus_mismatch = false
# print sequence name
html_string << sequence_names[index]
# loop through sequence blocks
(0..alignment.alignment_length-1).each do |alignment_position|
sequence_letter = sequence.slice(alignment_position,1).to_s
if sequence_letter == "X" or sequence_letter == "Z"# dodgy amino acid or stop
if consensus_mismatch == true
consensus_mismatch = false
html_string << "</span>"
end
# add base to html_string
if sequence_letter == "Z"
html_string << "<span style='background-color: #FF0000'>*</span>"
else
html_string << "<span style='background-color: #FF0000'>" + sequence_letter + "</span>"
end
elsif sequence_letter != consensus.slice(alignment_position,1).to_s # not a match
if consensus_mismatch == false
consensus_mismatch = true
html_string << "<span style='background-color: #{process_options['highlight_colour']}'>"
end
# add base to html_string
html_string << sequence_letter
else # a match
if consensus_mismatch == true
consensus_mismatch = false
html_string << "</span>"
end
# add base to html_string
if process_options['consensus']
html_string << "."
else
html_string << sequence_letter
end
end
end
html_string << "</span>" if consensus_mismatch == true
html_string << "<br/>"
#translate ?
if process_options['translate']
(max_name_length+1).times{html_string << "&nbsp;"}
(0..alignment.alignment_length-1).each do |alignment_position|
if alignment_position%3 == 0
amino_acid = Bio::CodonTable::TABLES[1][sequence.slice(alignment_position,3).downcase]
if amino_acid.nil?
if sequence.slice(alignment_position,3) == "---"
html_string << "&nbsp;"
else
html_string << "X"
end
else
html_string << "#{amino_acid}"
end
else
html_string << "&nbsp;"
end
end
html_string << "<br/>"
end
end # end of sequence loop
# ruler drawing
if process_options['draw_ruler']
# draw ticks
(max_name_length+1).times do html_string << "&nbsp;" end
(((block_number-1)*process_options['block_size'])+1..(block_number*process_options['block_size'])).each do |alignment_position|
break if alignment_position > ((block_number-1)*process_options['block_size']) + alignment.alignment_length
if alignment_position%10 == 0
html_string << "|"
else
html_string << "&nbsp;"
end
end
# end
html_string << "<br/>"
# draw numbers
(max_name_length+1).times do html_string << "&nbsp;" end
alignment_position = ((block_number-1)*process_options['block_size'])+1
while alignment_position <= (block_number*process_options['block_size']) do
break if alignment_position > ((block_number-1)*process_options['block_size']) + alignment.alignment_length
if alignment_position%10 == 0
html_string << alignment_position.to_s
alignment_position += alignment_position.to_s.length
else
html_string << "&nbsp;"
alignment_position += 1
end
end
html_string << "<br/>"
end # end of ruler drawing
html_string << "<br/>"
{'block_number' => block_number , 'html_string' => html_string}
end
# Merge all resulting htmls into one
def merge
all_htmls = Array.new
input.each do |html_data|
all_htmls[html_data['block_number']-1] = html_data['html_string']
end
final_html_string = ""
all_htmls.each do |html_string|
final_html_string << html_string
end
final_html_string
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment