+++ /dev/null
-# Copyright (C) 2007-2011 Martin A. Hansen.
-
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-# http://www.gnu.org/copyleft/gpl.html
-
-# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-# This software is part of the Biopieces framework (www.biopieces.org).
-
-# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-require 'inline' # RubyInline
-
-# Error class for all exceptions to do with BackTrack.
-class BackTrackError < StandardError; end
-
-# Module containing code to locate nucleotide patterns in sequences allowing for
-# ambiguity codes and a given maximum mismatches, insertions, and deletions. The
-# pattern match engine is based on a backtrack algorithm.
-# Insertions are nucleotides found in the pattern but not in the sequence.
-# Deletions are nucleotides found in the sequence but not in the pattern.
-# Algorithm based on code kindly provided by j_random_hacker @ Stackoverflow:
-# http://stackoverflow.com/questions/7557017/approximate-string-matching-using-backtracking/
-module BackTrack
- OK_PATTERN = Regexp.new('^[bflsycwphqrimtnkvadegu]+$')
- MAX_MIS = 5 # Maximum number of mismatches allowed
- MAX_INS = 5 # Maximum number of insertions allowed
- MAX_DEL = 5 # Maximum number of deletions allowed
-
- # ------------------------------------------------------------------------------
- # str.scan(pattern[, max_mismatches [, max_insertions [,max_deletions]]])
- # -> Array
- # str.scan(pattern[, max_mismatches [, max_insertions [,max_deletions]]]) { |match|
- # block
- # }
- # -> Match
- #
- # ------------------------------------------------------------------------------
- # Method to iterate through a sequence to locate pattern matches starting at a
- # given offset allowing for a maximum number of mismatches, insertions, and
- # deletions. Insertions are nucleotides found in the pattern but not in the
- # sequence. Deletions are nucleotides found in the sequence but not in the
- # pattern. Matches found in block context return the Match object. Otherwise
- # matches are returned in an Array of Match objects.
- def patscan(pattern, offset = 0, max_mismatches = 0, max_insertions = 0, max_deletions = 0)
- raise BackTrackError, "Bad pattern: #{pattern}" unless pattern.downcase =~ OK_PATTERN
- raise BackTrackError, "offset: #{offset} out of range (0 ... #{self.length - 1})" unless (0 ... self.length).include? offset
- raise BackTrackError, "max_mismatches: #{max_mismatches} out of range (0 .. #{MAX_MIS})" unless (0 .. MAX_MIS).include? max_mismatches
- raise BackTrackError, "max_insertions: #{max_insertions} out of range (0 .. #{MAX_INS})" unless (0 .. MAX_INS).include? max_insertions
- raise BackTrackError, "max_deletions: #{max_deletions} out of range (0 .. #{MAX_DEL})" unless (0 .. MAX_DEL).include? max_deletions
-
- matches = []
-
- if block_given?
- while result = self.track(pattern, offset, max_mismatches, max_insertions, max_deletions)
- yield Match.new(result.first, result.last, self.seq[result.first ... result.first + result.last])
- offset = result.first + 1
- end
- else
- while result = self.track(pattern, offset, max_mismatches, max_insertions, max_deletions)
- matches << Match.new(result.first, result.last, self.seq[result.first ... result.first + result.last])
- offset = result.first + 1
- end
- end
-
- return matches.empty? ? nil : matches unless block_given?
- end
-
- private
-
- inline do |builder|
- builder.add_static "id_seq", 'rb_intern("@seq")', "ID"
-
- # Macro for matching nucleotides including ambiguity codes.
- builder.prefix %{
- #define MATCH(A,B) ((bitmap[(unsigned short) A] & bitmap[(unsigned short) B]) != 0)
- }
-
- # Bitmap for matching nucleotides including ambiguity codes.
- # For each value bits are set from the left: bit pos 1 for A,
- # bit pos 2 for T, bit pos 3 for C, and bit pos 4 for G.
- builder.prefix %{
- unsigned short bitmap[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0,
- 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0,
- 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0,
- 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- }
-
- # Backtrack algorithm for matching a pattern (p) starting in a sequence (s) allowing for mm
- # mismatches, ins insertions and del deletions. ss is the start of the sequence, used only for
- # reporting the match endpoints.
- builder.prefix %{
- unsigned int backtrack(char* ss, char* s, char* p, int mm, int ins, int del)
- {
- unsigned int r = 0;
-
- while (*s && MATCH(*s, *p)) ++s, ++p; // OK to always match longest segment
-
- if (!*p)
- return (unsigned int) (s - ss);
- else
- {
- if (mm && *s && *p && (r = backtrack(ss, s + 1, p + 1, mm - 1, ins, del))) return r;
- if (ins && *p && (r = backtrack(ss, s, p + 1, mm, ins - 1, del))) return r;
- if (del && *s && (r = backtrack(ss, s + 1, p, mm, ins, del - 1))) return r;
- }
-
- return 0;
- }
- }
-
- # Find pattern (p) in a sequence (@seq) starting at pos, with at most mm mismatches, ins
- # insertions and del deletions.
- builder.c %{
- static VALUE track(char* p, unsigned int pos, int mm, int ins, int del)
- {
- VALUE seq = rb_ivar_get(self, id_seq);
- char* s = StringValuePtr(seq);
- char* ss = s;
- unsigned int e;
- VALUE tuple;
-
- if (pos < strlen(s))
- {
- s += pos;
-
- while (*s)
- {
- if (e = backtrack(ss, s, p, mm, ins, del))
- {
- tuple = rb_ary_new();
- rb_ary_push(tuple, INT2FIX((int) (s - ss)));
- rb_ary_push(tuple, INT2FIX((int) e - (s - ss)));
- return tuple;
- }
-
- s++;
- }
- }
-
- return Qnil;
- }
- }
- end
-
- # Class containing match information.
- class Match
- attr_reader :pos, :length, :match
-
- def initialize(pos, length, match)
- @pos = pos
- @length = length
- @match = match
- end
-
- def to_s
- "#{pos}:#{length}:#{match}"
- end
- end
-end
-
-
-__END__
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
require 'maasha/bits'
-require 'maasha/backtrack'
+require 'maasha/seq/backtrack'
require 'maasha/seq/digest'
require 'maasha/seq/patternmatcher'
require 'maasha/seq/trim'
--- /dev/null
+# Copyright (C) 2007-2011 Martin A. Hansen.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# http://www.gnu.org/copyleft/gpl.html
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+# This software is part of the Biopieces framework (www.biopieces.org).
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+require 'inline' # RubyInline
+
+# Error class for all exceptions to do with BackTrack.
+class BackTrackError < StandardError; end
+
+# Module containing code to locate nucleotide patterns in sequences allowing for
+# ambiguity codes and a given maximum mismatches, insertions, and deletions. The
+# pattern match engine is based on a backtrack algorithm.
+# Insertions are nucleotides found in the pattern but not in the sequence.
+# Deletions are nucleotides found in the sequence but not in the pattern.
+# Algorithm based on code kindly provided by j_random_hacker @ Stackoverflow:
+# http://stackoverflow.com/questions/7557017/approximate-string-matching-using-backtracking/
+module BackTrack
+ OK_PATTERN = Regexp.new('^[bflsycwphqrimtnkvadegu]+$')
+ MAX_MIS = 5 # Maximum number of mismatches allowed
+ MAX_INS = 5 # Maximum number of insertions allowed
+ MAX_DEL = 5 # Maximum number of deletions allowed
+
+ # ------------------------------------------------------------------------------
+ # str.scan(pattern[, max_mismatches [, max_insertions [,max_deletions]]])
+ # -> Array
+ # str.scan(pattern[, max_mismatches [, max_insertions [,max_deletions]]]) { |match|
+ # block
+ # }
+ # -> Match
+ #
+ # ------------------------------------------------------------------------------
+ # Method to iterate through a sequence to locate pattern matches starting at a
+ # given offset allowing for a maximum number of mismatches, insertions, and
+ # deletions. Insertions are nucleotides found in the pattern but not in the
+ # sequence. Deletions are nucleotides found in the sequence but not in the
+ # pattern. Matches found in block context return the Match object. Otherwise
+ # matches are returned in an Array of Match objects.
+ def patscan(pattern, offset = 0, max_mismatches = 0, max_insertions = 0, max_deletions = 0)
+ raise BackTrackError, "Bad pattern: #{pattern}" unless pattern.downcase =~ OK_PATTERN
+ raise BackTrackError, "offset: #{offset} out of range (0 ... #{self.length - 1})" unless (0 ... self.length).include? offset
+ raise BackTrackError, "max_mismatches: #{max_mismatches} out of range (0 .. #{MAX_MIS})" unless (0 .. MAX_MIS).include? max_mismatches
+ raise BackTrackError, "max_insertions: #{max_insertions} out of range (0 .. #{MAX_INS})" unless (0 .. MAX_INS).include? max_insertions
+ raise BackTrackError, "max_deletions: #{max_deletions} out of range (0 .. #{MAX_DEL})" unless (0 .. MAX_DEL).include? max_deletions
+
+ matches = []
+
+ if block_given?
+ while result = self.track(pattern, offset, max_mismatches, max_insertions, max_deletions)
+ yield Match.new(result.first, result.last, self.seq[result.first ... result.first + result.last])
+ offset = result.first + 1
+ end
+ else
+ while result = self.track(pattern, offset, max_mismatches, max_insertions, max_deletions)
+ matches << Match.new(result.first, result.last, self.seq[result.first ... result.first + result.last])
+ offset = result.first + 1
+ end
+ end
+
+ return matches.empty? ? nil : matches unless block_given?
+ end
+
+ private
+
+ inline do |builder|
+ builder.add_static "id_seq", 'rb_intern("@seq")', "ID"
+
+ # Macro for matching nucleotides including ambiguity codes.
+ builder.prefix %{
+ #define MATCH(A,B) ((bitmap[(unsigned short) A] & bitmap[(unsigned short) B]) != 0)
+ }
+
+ # Bitmap for matching nucleotides including ambiguity codes.
+ # For each value bits are set from the left: bit pos 1 for A,
+ # bit pos 2 for T, bit pos 3 for C, and bit pos 4 for G.
+ builder.prefix %{
+ unsigned short bitmap[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0,
+ 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0,
+ 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0,
+ 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ }
+
+ # Backtrack algorithm for matching a pattern (p) starting in a sequence (s) allowing for mm
+ # mismatches, ins insertions and del deletions. ss is the start of the sequence, used only for
+ # reporting the match endpoints.
+ builder.prefix %{
+ unsigned int backtrack(char* ss, char* s, char* p, int mm, int ins, int del)
+ {
+ unsigned int r = 0;
+
+ while (*s && MATCH(*s, *p)) ++s, ++p; // OK to always match longest segment
+
+ if (!*p)
+ return (unsigned int) (s - ss);
+ else
+ {
+ if (mm && *s && *p && (r = backtrack(ss, s + 1, p + 1, mm - 1, ins, del))) return r;
+ if (ins && *p && (r = backtrack(ss, s, p + 1, mm, ins - 1, del))) return r;
+ if (del && *s && (r = backtrack(ss, s + 1, p, mm, ins, del - 1))) return r;
+ }
+
+ return 0;
+ }
+ }
+
+ # Find pattern (p) in a sequence (@seq) starting at pos, with at most mm mismatches, ins
+ # insertions and del deletions.
+ builder.c %{
+ static VALUE track(char* p, unsigned int pos, int mm, int ins, int del)
+ {
+ VALUE seq = rb_ivar_get(self, id_seq);
+ char* s = StringValuePtr(seq);
+ char* ss = s;
+ unsigned int e;
+ VALUE tuple;
+
+ if (pos < strlen(s))
+ {
+ s += pos;
+
+ while (*s)
+ {
+ if (e = backtrack(ss, s, p, mm, ins, del))
+ {
+ tuple = rb_ary_new();
+ rb_ary_push(tuple, INT2FIX((int) (s - ss)));
+ rb_ary_push(tuple, INT2FIX((int) e - (s - ss)));
+ return tuple;
+ }
+
+ s++;
+ }
+ }
+
+ return Qnil;
+ }
+ }
+ end
+
+ # Class containing match information.
+ class Match
+ attr_reader :pos, :length, :match
+
+ def initialize(pos, length, match)
+ @pos = pos
+ @length = length
+ @match = match
+ end
+
+ def to_s
+ "#{pos}:#{length}:#{match}"
+ end
+ end
+end
+
+
+__END__
--- /dev/null
+#!/usr/bin/env ruby
+$:.unshift File.join(File.dirname(__FILE__),'..','lib')
+
+# Copyright (C) 2007-2011 Martin A. Hansen.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# http://www.gnu.org/copyleft/gpl.html
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+# This software is part of the Biopieces framework (www.biopieces.org).
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+require 'test/unit'
+require 'maasha/seq'
+
+class BackTrackTest < Test::Unit::TestCase
+ def setup
+ # 0 1
+ # 01234567890123456789
+ @seq = Seq.new("test", "tacgatgctagcatgcacgg")
+ end
+
+ def test_BackTrack_patscan_with_bad_pattern_raises
+ ["", "X", "1"].each { |pattern|
+ assert_raise(BackTrackError) { @seq.patscan(pattern) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_OK_pattern_dont_raise
+ ["N", "atcg"].each { |pattern|
+ assert_nothing_raised { @seq.patscan(pattern) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_bad_pos_raises
+ [-1, 20].each { |pos|
+ assert_raise(BackTrackError) { @seq.patscan("N", pos) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_OK_pos_dont_raise
+ [0, 19].each { |pos|
+ assert_nothing_raised { @seq.patscan("N", pos) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_bad_mis_raises
+ [-1, 6].each { |mis|
+ assert_raise(BackTrackError) { @seq.patscan("N", 0, mis) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_OK_mis_dont_raise
+ [0, 5].each { |mis|
+ assert_nothing_raised { @seq.patscan("N", 0, mis) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_bad_ins_raises
+ [-1, 6].each { |ins|
+ assert_raise(BackTrackError) { @seq.patscan("N", 0, 0, ins) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_OK_ins_dont_raise
+ [0, 5].each { |ins|
+ assert_nothing_raised { @seq.patscan("N", 0, 0, ins) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_bad_del_raises
+ [-1, 6].each { |del|
+ assert_raise(BackTrackError) { @seq.patscan("N", 0, 0, 0, del) }
+ }
+ end
+
+ def test_BackTrack_patscan_with_OK_del_dont_raise
+ [0, 5].each { |del|
+ assert_nothing_raised { @seq.patscan("N", 0, 0, 0, del) }
+ }
+ end
+
+ def test_BackTrack_patscan_perfect_left_is_ok
+ assert_equal("0:7:tacgatg", @seq.patscan("TACGATG").first.to_s)
+ end
+
+ def test_BackTrack_patscan_perfect_right_is_ok
+ assert_equal("13:7:tgcacgg", @seq.patscan("TGCACGG").first.to_s)
+ end
+
+ def test_BackTrack_patscan_ambiguity_is_ok
+ assert_equal("13:7:tgcacgg", @seq.patscan("TGCACNN").first.to_s)
+ end
+
+ def test_BackTrack_patscan_pos_is_ok
+ assert_equal("10:1:g", @seq.patscan("N", 10).first.to_s)
+ assert_equal("19:1:g", @seq.patscan("N", 10).last.to_s)
+ end
+
+ def test_BackTrack_patscan_mis_left_is_ok
+ assert_equal("0:7:tacgatg", @seq.patscan("Aacgatg", 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_mis_right_is_ok
+ assert_equal("13:7:tgcacgg", @seq.patscan("tgcacgA", 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_ins_left_is_ok
+ assert_equal("0:7:tacgatg", @seq.patscan("Atacgatg", 0, 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_ins_right_is_ok
+ assert_equal("13:7:tgcacgg", @seq.patscan("tgcacggA", 0, 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_del_left_is_ok
+ assert_equal("0:7:tacgatg", @seq.patscan("acgatg", 0, 0, 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_del_right_is_ok
+ assert_equal("12:8:atgcacgg", @seq.patscan("tgcacgg", 0, 0, 0, 1).first.to_s)
+ end
+
+ def test_BackTrack_patscan_ambiguity_mis_ins_del_all_ok
+ assert_equal("0:20:tacgatgctagcatgcacgg", @seq.patscan("tacatgcNagGatgcCacgg", 0, 1, 1, 1).first.to_s)
+ end
+end
+
+++ /dev/null
-#!/usr/bin/env ruby
-$:.unshift File.join(File.dirname(__FILE__),'..','lib')
-
-# Copyright (C) 2007-2011 Martin A. Hansen.
-
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-# http://www.gnu.org/copyleft/gpl.html
-
-# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-# This software is part of the Biopieces framework (www.biopieces.org).
-
-# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-require 'test/unit'
-require 'maasha/seq'
-
-class BackTrackTest < Test::Unit::TestCase
- def setup
- # 0 1
- # 01234567890123456789
- @seq = Seq.new("test", "tacgatgctagcatgcacgg")
- end
-
- def test_BackTrack_patscan_with_bad_pattern_raises
- ["", "X", "1"].each { |pattern|
- assert_raise(BackTrackError) { @seq.patscan(pattern) }
- }
- end
-
- def test_BackTrack_patscan_with_OK_pattern_dont_raise
- ["N", "atcg"].each { |pattern|
- assert_nothing_raised { @seq.patscan(pattern) }
- }
- end
-
- def test_BackTrack_patscan_with_bad_pos_raises
- [-1, 20].each { |pos|
- assert_raise(BackTrackError) { @seq.patscan("N", pos) }
- }
- end
-
- def test_BackTrack_patscan_with_OK_pos_dont_raise
- [0, 19].each { |pos|
- assert_nothing_raised { @seq.patscan("N", pos) }
- }
- end
-
- def test_BackTrack_patscan_with_bad_mis_raises
- [-1, 6].each { |mis|
- assert_raise(BackTrackError) { @seq.patscan("N", 0, mis) }
- }
- end
-
- def test_BackTrack_patscan_with_OK_mis_dont_raise
- [0, 5].each { |mis|
- assert_nothing_raised { @seq.patscan("N", 0, mis) }
- }
- end
-
- def test_BackTrack_patscan_with_bad_ins_raises
- [-1, 6].each { |ins|
- assert_raise(BackTrackError) { @seq.patscan("N", 0, 0, ins) }
- }
- end
-
- def test_BackTrack_patscan_with_OK_ins_dont_raise
- [0, 5].each { |ins|
- assert_nothing_raised { @seq.patscan("N", 0, 0, ins) }
- }
- end
-
- def test_BackTrack_patscan_with_bad_del_raises
- [-1, 6].each { |del|
- assert_raise(BackTrackError) { @seq.patscan("N", 0, 0, 0, del) }
- }
- end
-
- def test_BackTrack_patscan_with_OK_del_dont_raise
- [0, 5].each { |del|
- assert_nothing_raised { @seq.patscan("N", 0, 0, 0, del) }
- }
- end
-
- def test_BackTrack_patscan_perfect_left_is_ok
- assert_equal("0:7:tacgatg", @seq.patscan("TACGATG").first.to_s)
- end
-
- def test_BackTrack_patscan_perfect_right_is_ok
- assert_equal("13:7:tgcacgg", @seq.patscan("TGCACGG").first.to_s)
- end
-
- def test_BackTrack_patscan_ambiguity_is_ok
- assert_equal("13:7:tgcacgg", @seq.patscan("TGCACNN").first.to_s)
- end
-
- def test_BackTrack_patscan_pos_is_ok
- assert_equal("10:1:g", @seq.patscan("N", 10).first.to_s)
- assert_equal("19:1:g", @seq.patscan("N", 10).last.to_s)
- end
-
- def test_BackTrack_patscan_mis_left_is_ok
- assert_equal("0:7:tacgatg", @seq.patscan("Aacgatg", 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_mis_right_is_ok
- assert_equal("13:7:tgcacgg", @seq.patscan("tgcacgA", 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_ins_left_is_ok
- assert_equal("0:7:tacgatg", @seq.patscan("Atacgatg", 0, 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_ins_right_is_ok
- assert_equal("13:7:tgcacgg", @seq.patscan("tgcacggA", 0, 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_del_left_is_ok
- assert_equal("0:7:tacgatg", @seq.patscan("acgatg", 0, 0, 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_del_right_is_ok
- assert_equal("12:8:atgcacgg", @seq.patscan("tgcacgg", 0, 0, 0, 1).first.to_s)
- end
-
- def test_BackTrack_patscan_ambiguity_mis_ins_del_all_ok
- assert_equal("0:20:tacgatgctagcatgcacgg", @seq.patscan("tacatgcNagGatgcCacgg", 0, 1, 1, 1).first.to_s)
- end
-end
-