# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
require 'pp'
-require 'tempfile'
+require 'open3'
require 'narray'
require 'maasha/fasta'
ROW_C = 2
ROW_G = 3
+class Fasta
+ def initialize(io)
+ @io = io
+ end
+
+ def close
+ @io.close
+ end
+end
+
# Class for aligning sequences.
class Align
# Class method to align sequences in a list of Seq objects and
# return these as a new list of Seq objects.
def self.muscle(entries, verbose = false)
- file_in = Tempfile.new("input")
- file_out = Tempfile.new("output")
result = []
index = {}
- Fasta.open(file_in, "w") do |ios|
+ Open3.popen3("muscle", "-quiet") do |stdin, stdout, stderr|
entries.each do |entry|
raise AlignError, "Duplicate sequence name: #{entry.seq_name}" if index.has_key? entry.seq_name
index[entry.seq_name] = entry
- ios.puts entry.to_fasta
+ stdin.puts entry.to_fasta
end
- end
- if verbose
- cmd = "muscle < #{file_in.path} > #{file_out.path}"
- else
- cmd = "muscle -quiet < #{file_in.path} > #{file_out.path}"
- end
+ stdin.close
+
+ stderr.each_line { |line| $stderr.puts line } if verbose
- system(cmd)
- raise AlignError, "command failed: #{cmd}" unless $?.success?
+ aligned_entries = Fasta.new(stdout)
- Fasta.open(file_out, "r") do |ios|
- ios.each do |fa_entry|
+ aligned_entries.each do |fa_entry|
fq_entry = index[fa_entry.seq_name]
fa_entry.seq.scan(/-+/) do |m|