+ BOOST_CHECK_EQUAL( m1.get_window(), 30 );
+ BOOST_CHECK_EQUAL( m1.get_threshold(), 20);
+ BOOST_CHECK_EQUAL( m1.is_dirty(), true);
+ BOOST_CHECK_EQUAL( m1.get_analysis_path().string(), "");
+}
+
+BOOST_AUTO_TEST_CASE( mussa_valid_motifs_in_new_analysis )
+{
+ Mussa m1;
+ fs::path full_path(fs::path(EXAMPLE_DIR, fs::native) / "mck3test.mupa");
+ m1.load_mupa_file( full_path );
+ m1.analyze();
+ // check motifs
+ BOOST_CHECK( m1.sequences().size() > 0 );
+ BOOST_CHECK_EQUAL( m1.sequences()[0]->motifs().size(), 0 );
+}
+
+// make sure we know that mupa files cannot be directories
+BOOST_AUTO_TEST_CASE( mussa_mupa_is_file_not_directory )
+{
+ fs::path curdir(".");
+ Mussa m1;
+ BOOST_CHECK_THROW(m1.load_mupa_file( curdir ), mussa_load_error );
+}
+
+// catch error if annotation isn't a file
+BOOST_AUTO_TEST_CASE( mussa_annotation_is_not_file )
+{
+ Mussa m1;
+ fs::path full_path(fs::path(EXAMPLE_DIR, fs::native) / "directory.mupa");
+ BOOST_CHECK_THROW( m1.load_mupa_file( full_path ), mussa_load_error );
+}
+
+BOOST_AUTO_TEST_CASE( mussa_load_analysis )
+{
+ fs::path example_dir(EXAMPLE_DIR, fs::native);
+ Mussa m1;
+ m1.load_mupa_file( example_dir / "mck3test.mupa" );
+ m1.analyze();
+
+ Mussa m2;
+ fs::path analysis_path = fs::initial_path() / "mck3test_w30_t20";
+ m2.load( analysis_path );
+
+ BOOST_CHECK_EQUAL( m1.size(), m2.size() );
+ BOOST_CHECK_EQUAL( m1.get_window(), m2.get_window() );
+ BOOST_CHECK_EQUAL( m1.get_threshold(), m2.get_threshold() );
+ BOOST_CHECK_EQUAL( m2.get_analysis_path().string(), analysis_path.string());
+}
+
+BOOST_AUTO_TEST_CASE( mussa_load_motif )
+{
+ string data = "AAGG 1.0 1.0 0.0\n"
+ "GGTT 0.0 0.1 1.0 1.0\n";
+
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ m1.load_motifs(test_istream);
+
+ BOOST_CHECK_EQUAL( m1.motifs().size(), 2);
+ for (Mussa::vector_sequence_type::const_iterator seq_i = m1.sequences().begin();
+ seq_i != m1.sequences().end();
+ ++seq_i)
+ {
+ BOOST_CHECK( (*seq_i)->motifs().size() > 0 );
+ }
+}
+
+BOOST_AUTO_TEST_CASE( mussa_load_broken_motif )
+{
+ string data = "AAGG 1.0 1.0 0.0\n"
+ "GGTT 0.0 0.1 1.0 1.0\n"
+ "ZZCTA 0.1 0.0 1.0\n";
+
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ BOOST_CHECK_THROW(m1.load_motifs(test_istream), motif_load_error);
+
+ BOOST_CHECK_EQUAL( m1.motifs().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE( mussa_named_motif )
+{
+ string data = "CCAATT cat 0.1 0.2 0.3\n";
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ m1.load_motifs(test_istream);
+
+ std::set<Sequence> motifs = m1.motifs();
+ BOOST_REQUIRE_EQUAL(motifs.size(), 1);
+ BOOST_CHECK_EQUAL(motifs.begin()->get_name(), "cat");
+}
+
+BOOST_AUTO_TEST_CASE( mussa_weirdly_spaced_named_motif )
+{
+ string data = "CCAATT cat_meow123 0.1 0.2 0.3\n";
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ m1.load_motifs(test_istream);
+
+ std::set<Sequence> motifs = m1.motifs();
+ BOOST_REQUIRE_EQUAL(motifs.size(), 1);
+ BOOST_CHECK_EQUAL(motifs.begin()->get_name(), "cat_meow123");
+}
+
+BOOST_AUTO_TEST_CASE( mussa_name_quoted_motif )
+{
+ string data = "CCAATT \"cat meow 123\" 0.1 0.2 0.3\n";
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ m1.load_motifs(test_istream);
+
+ std::set<Sequence> motifs = m1.motifs();
+ BOOST_REQUIRE_EQUAL(motifs.size(), 1);
+ BOOST_CHECK_EQUAL(motifs.begin()->get_name(), "cat meow 123");
+}
+
+BOOST_AUTO_TEST_CASE( mussa_name_embedded_quote_motif )
+{
+ // pretty obviously this shouldn't work as " are our delimiter
+ // and i'm too lazy to add support for \ in the parser
+ string data = "ATA 0.5 0.5 0.5\n"
+ "CCAATT \"cat \"meow 123\" 0.1 0.2 0.3\n";
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ BOOST_CHECK_THROW( m1.load_motifs(test_istream), motif_load_error);
+
+ std::set<Sequence> motifs = m1.motifs();
+ BOOST_REQUIRE_EQUAL(motifs.size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE( mussa_save_motif )
+{
+ string data = "ATA 1 1 1 1\n"
+ "CAT \"my name\" 1 0 0.5 0.5\n";
+ istringstream data_istream(data);
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTCCAATT");
+ m1.load_motifs(data_istream);
+
+ string save;
+ ostringstream save_ostream(save);
+ m1.save_motifs(save_ostream);
+
+ istringstream reloaded_istream(save_ostream.str());
+ Mussa m2;
+ m2.append_sequence("AAAAGGGGTTTT");
+ m2.append_sequence("GGGCCCCTTCCAATT");
+ m2.load_motifs(reloaded_istream);
+
+ BOOST_REQUIRE_EQUAL(m1.motifs().size(), m2.motifs().size());
+ Mussa::motif_set::const_iterator m1motif = m1.motifs().begin();
+ Mussa::motif_set::const_iterator m2motif = m2.motifs().begin();
+ for (;
+ m1motif != m1.motifs().end() and m2motif != m2.motifs().end();
+ ++m1motif, ++m2motif)
+ {
+ BOOST_CHECK_EQUAL(m1motif->get_sequence(), m2motif->get_sequence());
+ BOOST_CHECK_EQUAL(m1motif->get_name(), m2motif->get_name());
+ BOOST_CHECK_EQUAL(m1.colorMapper()->lookup("motif", m1motif->get_sequence()),
+ m2.colorMapper()->lookup("motif", m2motif->get_sequence()));
+ }
+}
+
+BOOST_AUTO_TEST_CASE( mussa_add_motif )
+{
+ vector<Sequence> motifs;
+ motifs.push_back("AAGG");
+ vector<Color> colors;
+ colors.push_back(Color(1.0, 0.0, 0.0));
+
+ Mussa m1;
+ m1.append_sequence("AAAAGGGGTTTT");
+ m1.append_sequence("GGGCCCCTTGGTT");
+ m1.set_motifs(motifs, colors);
+ int first_size = m1.motifs().size();
+ BOOST_CHECK_EQUAL( first_size, 1 );
+ BOOST_REQUIRE(first_size > 0);
+ BOOST_CHECK_EQUAL(*(m1.motifs().begin()), motifs.front());
+ // make sure that our sequences have the right number of motifs
+ BOOST_CHECK_EQUAL(m1.sequences()[0]->motifs().size(), 1);
+ BOOST_CHECK_EQUAL(m1.sequences()[1]->motifs().size(), 1); // because of rc
+
+ // verify that setting the motif clears the arrays
+ m1.set_motifs(motifs, colors);
+ BOOST_CHECK_EQUAL( first_size, m1.motifs().size() );
+ // make sure that our sequences have the right number of motifs
+ BOOST_CHECK_EQUAL(m1.sequences()[0]->motifs().size(), 1);
+ BOOST_CHECK_EQUAL(m1.sequences()[1]->motifs().size(), 1);
+
+ // add a different motif
+ motifs.clear();
+ motifs.push_back("CCTTGG");
+ BOOST_CHECK_EQUAL(motifs.size(), 1);
+ m1.set_motifs(motifs, colors);
+ BOOST_CHECK_EQUAL(m1.motifs().size(), 1);
+ BOOST_REQUIRE(m1.motifs().size() > 0);
+ BOOST_CHECK_EQUAL(*(m1.motifs().begin()), motifs.front());
+ BOOST_CHECK_EQUAL(m1.sequences()[0]->motifs().size(), 0);
+ BOOST_CHECK_EQUAL(m1.sequences()[1]->motifs().size(), 1);
+
+ // try a motif that doesn't exist
+ motifs.clear();
+ motifs.push_back("CCTTGG");
+ BOOST_CHECK_EQUAL(motifs.size(), 1);
+ m1.set_motifs(motifs, colors);
+ BOOST_CHECK_EQUAL(m1.motifs().size(), 1);
+ BOOST_CHECK_EQUAL(m1.sequences()[0]->motifs().size(), 0);
+ BOOST_CHECK_EQUAL(m1.sequences()[1]->motifs().size(), 1);
+
+}
+
+static void
+two_way_local_align_test(const Mussa::vector_sequence_type &seqs,
+ const list<ConservedPath::path_type>& result,
+ const list<vector<bool> >& reversed)
+{
+ map<char, vector <char> > m;
+ assign::insert(m)('A', assign::list_of('A')('T') )
+ ('T', assign::list_of('T')('A') )
+ ('G', assign::list_of('G')('C') )
+ ('C', assign::list_of('C')('G') );
+ list<vector<bool> >::const_iterator rc_i = reversed.begin();
+
+ for(list<ConservedPath::path_type>::const_iterator base_i = result.begin();
+ base_i != result.end();
+ ++base_i, ++rc_i)
+ {
+ // since the reverse compliment flag is relative to the first sequence
+ // the first one should always be false
+ BOOST_CHECK_EQUAL( (*rc_i)[0], false );
+ const int first_path_basepair_index = (*base_i)[0];
+ const int second_path_basepair_index = (*base_i)[1];
+ const char first_basepair = (*seqs[0])[first_path_basepair_index];
+ const char second_basepair = (*seqs[1])[second_path_basepair_index];
+ // get our index into our reverse compliment map m
+ const int second_compliment_index = (*rc_i)[1];
+ // lookup the forward or reverse compliment depending on our rc flag
+ const char complimented_second = m[second_basepair][second_compliment_index];
+
+ BOOST_CHECK_EQUAL( first_basepair, complimented_second) ;
+ }