fix problems with motif changes not showing up in sequencebrowser
authorDiane Trout <diane@caltech.edu>
Tue, 3 Apr 2007 23:39:44 +0000 (23:39 +0000)
committerDiane Trout <diane@caltech.edu>
Tue, 3 Apr 2007 23:39:44 +0000 (23:39 +0000)
This patch adds a couple of new unit test cases to make sure that
when the motif sequence list is changed it is actually reflected
in the sequence browser.

The problem was that when I originally coded it, a GlSequence held
a shared_ptr<Sequence> so even though SequenceBrowser had new copies
of GlSequence, the underlying Sequence was still shared.

The change to GlSequence being a subclass of Sequence with a copy
of the motif_list meant that changes to the motif_list in one
copy weren't reflected in the copy held by the SequenceBrowser.

I fixed it by changing sequence to hold a shared_ptr<list<motif> >.
the downside is that that the motif_list is now always shared
between copies of a Sequence, which is likely to cause problems
when opening a second mussa window.

However since I plan on tossing the current annotation and motif handling
code at some point in the near future, this patch should be "good
enough".

16 files changed:
alg/annotation_colors.hpp
alg/glseqbrowser.cpp
alg/glseqbrowser.hpp
alg/glsequence.cpp
alg/glsequence.hpp
alg/mussa.cpp
alg/sequence.cpp
alg/sequence.hpp
alg/test/test_glseqbrowser.cpp
alg/test/test_sequence.cpp
qui/motif_editor/test/TestMotifEditor.hpp
qui/seqbrowser/SequenceBrowserWidget.cpp
qui/seqbrowser/SequenceBrowserWidget.hpp
qui/seqbrowser/test/CMakeLists.txt
qui/seqbrowser/test/TestSequenceBrowserWidget.cpp [new file with mode: 0644]
qui/seqbrowser/test/TestSequenceBrowserWidget.hpp [new file with mode: 0644]

index eaabc1784635f84725c74d832c37d42df909be2a..50c738b6867cc3092cf2c34dd6dd5d64dd3c9b9a 100644 (file)
@@ -4,6 +4,8 @@
 #include <map>
 #include <string>
 
+#include <boost/shared_ptr.hpp>
+
 #include "color.hpp"
 #include "sequence.hpp"
 
@@ -24,6 +26,9 @@ struct DefaultColorMap
   color_map_type cm;
 };
 
+class AnnotationColors;
+typedef boost::shared_ptr<AnnotationColors> AnnotationColorsRef;
+
 class AnnotationColors
 {
 public:
index 03afaf56c4fac3707735f9afa90752d96fea19ab..d04f6f3a199feb9cfaab21ad74996ee9d5ff24d0 100644 (file)
@@ -308,14 +308,14 @@ double GlSeqBrowser::zoom() const
   return zoom_level;
 }
 
-void GlSeqBrowser::setColorMapper(boost::shared_ptr<AnnotationColors> cm)
+void GlSeqBrowser::setColorMapper(AnnotationColorsRef cm)
 {
   color_mapper = cm;
 }
 
-const AnnotationColors& GlSeqBrowser::colorMapper()
+const AnnotationColorsRef GlSeqBrowser::colorMapper()
 {
-  return *color_mapper;
+  return color_mapper;
 }
 
 void GlSeqBrowser::clear()
@@ -362,7 +362,7 @@ void GlSeqBrowser::push_sequence(GlSequenceRef gs)
     path_segments.push_back(pair_segment_map());
 }
 
-const std::vector<boost::shared_ptr<GlSequence> >& GlSeqBrowser::sequences() const
+const std::vector<GlSequenceRef >& GlSeqBrowser::sequences() const
 {
   return track_container;
 }
index 38ede4bc05476ffa32458850db76aafe9ae1e368..dcbf4a653fc946b7c113e0329d004dad8a05d9b6 100644 (file)
@@ -69,7 +69,7 @@ public:
   void centerOnPath(const std::vector<int>&);
 
   void setColorMapper(boost::shared_ptr<AnnotationColors> cm);
-  const AnnotationColors& colorMapper();
+  const AnnotationColorsRef colorMapper();
 
   //! clear our tracks and connections
   void clear();
@@ -208,13 +208,13 @@ private:
   //! the center of our current viewport (world coord) (used for scrollbar)
   float viewport_center;
   double zoom_level;
-  boost::shared_ptr<AnnotationColors> color_mapper;
+  AnnotationColorsRef color_mapper;
   //! counter for each path added to us via connect
   int pathid;
 
 protected:
   //! container of all the GlSequences loaded into our scene
-  std::vector<boost::shared_ptr<GlSequence> > track_container;
+  std::vector<GlSequenceRef > track_container;
   //! where to draw our box (world coordinates)
   rect<float> selectedRegion;
   //! true if we have a selection
index 17fb561c830c5cf3fc241a01e8de2353c4cc8691..eb6cfe94574b49496dea22ca11e8498a5585f377 100644 (file)
@@ -257,7 +257,7 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
   // draw annotations
   GLfloat annotation_z = z() + 10.0;
   const std::list<annot>& annots = Sequence::annotations();
-  const std::list<motif>& motifs = Sequence::motifs();
+  const MotifList& motifs = Sequence::motifs();
   for (std::list<annot>::const_iterator annot_itor = annots.begin();
        annot_itor != annots.end();
        ++annot_itor)
@@ -267,7 +267,7 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
              height(), annotation_z);
   }
   // if motifs?
-  for (std::list<motif>::const_iterator motifs_itor = motifs.begin();
+  for (MotifList::const_iterator motifs_itor = motifs.begin();
        motifs_itor != motifs.end();
        ++motifs_itor)
   {
@@ -275,7 +275,6 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
     draw_box(left, right, x()+motifs_itor->begin, x()+motifs_itor->end, 
              height(), annotation_z+1.0);
   }
-
 }
 
 // this way of drawing characters, came from the red open gl book
index cbb933c6d3836717e4340e97aac5451bb55b8f12..4d93d15b66969aea13f3a51026352c58c9524a4a 100644 (file)
@@ -54,6 +54,8 @@ public:
   const ColorRef color() const;
   //! return our draw color
   ColorRef color();
+  //! return our annotation color mapper
+  AnnotationColorsRef colorMapper() { return color_mapper; }
 
   //! draw a track 
   /*! left and right are the edges of the current viewport
@@ -100,7 +102,7 @@ public:
   friend bool operator==(const GlSequence &left, const GlSequence &right);
 
 protected:
-  boost::shared_ptr<AnnotationColors> color_mapper;
+  AnnotationColorsRef color_mapper;
   const GLfloat char_pix_per_world_unit;
 
   //! Return the pixel width of the opengl viewport.
index 4b96d1b4d115a6f12915d1b3fd5a1d082d43212e..f75290c58705c68ea8e7ccb152da253fde976cbb 100644 (file)
@@ -835,7 +835,7 @@ void Mussa::update_sequences_motifs()
 {
   // once we've loaded all the motifs from the file, 
   // lets attach them to the sequences
-  for(vector<boost::shared_ptr<Sequence> >::iterator seq_i = the_seqs.begin();
+  for(vector<SequenceRef >::iterator seq_i = the_seqs.begin();
       seq_i != the_seqs.end();
       ++seq_i)
   {
index 608ddd3b2059ba808c283e7726b181bfb27e0ce2..ecbc633f80141b32fc5ea2f8ee7d512c149bf415 100644 (file)
@@ -90,7 +90,8 @@ Sequence::~Sequence()
 
 Sequence::Sequence(const char *seq, AlphabetRef alphabet_, SeqSpan::strand_type strand_)
   : header(""),
-    species("")
+    species(""),
+    motif_list(new MotifList)
 {
   set_filtered_sequence(seq, alphabet_, 0, npos, strand_);
 }
@@ -99,7 +100,8 @@ Sequence::Sequence(const std::string& seq,
                    AlphabetRef alphabet_,
                    SeqSpan::strand_type strand_) 
   : header(""),
-    species("")
+    species(""),
+    motif_list(new MotifList)
 {
   set_filtered_sequence(seq, alphabet_, 0, seq.size(), strand_);
 }
@@ -134,7 +136,8 @@ Sequence::Sequence(const SequenceRef o)
 Sequence::Sequence(const SeqSpanRef& seq_ref)
   : seq(seq_ref),
     header(""),
-    species("")
+    species(""),
+    motif_list(new MotifList)
 {
 }
 
@@ -637,7 +640,7 @@ Sequence::clear()
   header.clear();
   species.clear();
   annots.clear();
-  motif_list.clear();
+  motif_list.reset(new MotifList);
 }
 
 void
@@ -755,18 +758,21 @@ void Sequence::add_motif(const Sequence& a_motif)
       motif_start_i != motif_starts.end();
       ++motif_start_i)
   {
-    motif_list.push_back(motif(*motif_start_i, a_motif.get_sequence()));
+    motif_list->push_back(motif(*motif_start_i, a_motif.get_sequence()));
   }
 }
 
 void Sequence::clear_motifs()
 {
-  motif_list.clear();
+  if (motif_list) 
+    motif_list->clear();
+  else 
+    motif_list.reset(new MotifList);
 }
 
-const std::list<motif>& Sequence::motifs() const
+const Sequence::MotifList& Sequence::motifs() const
 {
-  return motif_list;
+  return *motif_list;
 }
 
 std::vector<int>
index fbd753fb46dc7d0142de209ece821626bd2e2577..9c7ddd4a1e9fb8a397e1332f95dd346ac19ca462 100644 (file)
@@ -105,6 +105,9 @@ public:
   typedef SeqString::const_reference const_reference;
   typedef SeqString::size_type size_type;
   static const size_type npos = SeqString::npos;
+  
+  typedef std::list<motif> MotifList;
+  typedef boost::shared_ptr<MotifList> MotifListRef;
                       
   Sequence(AlphabetRef a = reduced_dna_alphabet);
   Sequence(const char* seq, 
@@ -225,7 +228,7 @@ public:
   //! add an annotation to our list of annotations
   void add_annotation(const annot& a);
   const std::list<annot>& annotations() const;
-  const std::list<motif>& motifs() const;
+  const MotifList& motifs() const;
 
   //! add a motif to our list of motifs
   void add_motif(const Sequence& a_motif);
@@ -251,7 +254,7 @@ protected:
   //! store our oldstyle annotations
   std::list<annot> annots;
   //! a seperate list for motifs since we're currently not saving them
-  std::list<motif> motif_list;
+  MotifListRef motif_list;
 
   //! copy over all our annotation children
   void copy_children(Sequence &, size_type start, size_type count) const;
index bbed0623312d5252e4a80f8eab1403408ac376aa..acd450eef09d4d72aed63b89dc0bdb05fbe83008 100644 (file)
@@ -9,9 +9,10 @@ using namespace boost::assign;
 #include <list>
 #include <vector>
 
-#include "alg/annotation_colors.hpp"
-#include "alg/glseqbrowser.hpp"
-#include "alg/sequence.hpp"
+#include "annotation_colors.hpp"
+#include "glseqbrowser.hpp"
+#include "mussa.hpp"
+#include "sequence.hpp"
 
 using namespace std;
 
@@ -157,7 +158,7 @@ BOOST_AUTO_TEST_CASE( setSelectedPaths )
   Sequence seq0(s0);
   Sequence seq1(s1);
   Sequence seq2(s2);
-
+  
   GlSeqBrowser gt;
   gt.push_sequence(seq0);
   gt.push_sequence(seq1);
@@ -195,7 +196,6 @@ BOOST_AUTO_TEST_CASE( setSelectedTracks )
   gt.push_sequence(seq1);
   gt.push_sequence(seq2);
 
-
   BOOST_CHECK_EQUAL( gt.selectedTracks().size(), 0 );
   gt.appendSelectedTrack(0, 0, seq0.size());
   gt.appendSelectedTrack(2, 0, seq2.size());
@@ -218,5 +218,4 @@ BOOST_AUTO_TEST_CASE( setSelectedTracks )
   BOOST_CHECK_EQUAL(seq_locs.front().getSequence(), seq0);
   BOOST_CHECK_EQUAL(seq_locs.front().getLeft(), 0);
   BOOST_CHECK_EQUAL(seq_locs.front().getRight(), 2);
-
-}
+}
\ No newline at end of file
index 38852a5d6f90096ea17944374e25173845656af7..921c5ef7aa2437a177b6f8094279ccca50d71441 100644 (file)
@@ -33,6 +33,24 @@ BOOST_AUTO_TEST_CASE( sequence_copy_constructor )
   BOOST_CHECK_EQUAL(s->get_species(), "foo");
   BOOST_CHECK_EQUAL(c->get_species(), "bar");
 }
+
+BOOST_AUTO_TEST_CASE( sequence_copy_constructor_copy_motifs )
+{
+  SequenceRef s(new Sequence("AAAAGGGGAAAA"));
+  s->add_motif("AAGG");
+  BOOST_CHECK_EQUAL(s->motifs().size(), 1);
+  
+  SequenceRef c(new Sequence(s->subseq()));
+  BOOST_CHECK_EQUAL(c->motifs().size(), 1);
+  
+  s->clear_motifs();  
+  BOOST_CHECK_EQUAL(s->motifs().size(), 0);
+  // FIXME: Technically c shouldn't lose its motifs.
+  // FIXME: getting that to work is hard.
+  // BOOST_CHECK_EQUAL(c->motifs().size(), 1);
+  BOOST_CHECK_EQUAL(c->motifs().size(), 0);
+}
+
 BOOST_AUTO_TEST_CASE( sequence_get_sequence )
 {
        Sequence s;
index 273473a2e53fc229aae914afed500635fc503a88..af01cb86e087fe5c1e33dde8936000bb13449cab 100644 (file)
@@ -60,6 +60,57 @@ private slots:
     QVERIFY(sequences2[0]->motifs().size() == 1);
     QVERIFY(sequences2[1]->motifs().size() == 0);
     QVERIFY(cm->lookup("motif", "AAGG") == Color(0.0, 1.0, 0.0));
+    QVERIFY(m->colorMapper()->lookup("motif", "AAGG") == Color(0.0, 1.0, 0.0));
+    
+    QVERIFY(editor->get_analysis() == m);
+    QVERIFY(editor->get_model() == model);
+    QVERIFY(m->colorMapper() == cm);
+  }
+
+  void testEditMotifApply() {
+    std::vector<Sequence> motifs;
+    motifs.push_back("AAGG");
+    std::vector<Color> colors;
+    colors.push_back(Color(0.0, 0.0, 1.0));
+        
+    MussaRef m(new Mussa);
+    m->append_sequence("AAAAGGGG");
+    m->append_sequence("AAAACCCC");
+    m->set_motifs(motifs, colors);
+    
+    // do the sequences have the right motifs?
+    std::vector<SequenceRef> sequences1(m->sequences());
+    QVERIFY(sequences1[0]->get_sequence() == "AAAAGGGG");
+    QVERIFY(sequences1[1]->get_sequence() == "AAAACCCC");
+    QVERIFY(sequences1[0]->motifs().size() == 1);
+    QVERIFY(sequences1[1]->motifs().size() == 0);
+    
+    // get color
+    boost::shared_ptr<AnnotationColors> cm(m->colorMapper());
+    QVERIFY(cm->lookup("motif", "AAGG") == Color(0.0, 0.0, 1.0));
+        
+    MotifEditor *editor(new MotifEditor(m));
+    MotifModel *model(editor->get_model());
+    // the AATT motif and the empty motif
+    QVERIFY(model->size() == 2);
+    QModelIndex row0_color(model->index(0, MotifModel::ColorCell));
+    QModelIndex row0_sequence(model->index(0, MotifModel::SequenceCell));
+    QVERIFY(model->data(row0_sequence) == "AAGG");
+    
+    // change contents of cell
+    model->setData(row0_sequence, QVariant("AACC"));
+    // this is equivalent to pressing apply
+    editor->updateAnalysisMotifs();
+    QVERIFY(model->data(row0_sequence) == "AACC");
+
+    // does the mussa analysis have the right data?
+    std::vector<SequenceRef> sequences2(m->sequences());
+    QVERIFY(sequences2[0]->motifs().size() == 0);
+    QVERIFY(sequences2[1]->motifs().size() == 1);
+    QVERIFY(cm->lookup("motif", "AACC") == Color(0.0, 0.0, 1.0));
+    QVERIFY(m->colorMapper()->lookup("motif", "AACC") == Color(0.0, 0.0, 1.0));
+    QVERIFY(cm->lookup("motif", "AAGG") == Color(0.0, 0.0, 0.0));
+    QVERIFY(m->colorMapper()->lookup("motif", "AAGG") == Color(0.0, 0.0, 0.0));
     
     QVERIFY(editor->get_analysis() == m);
     QVERIFY(editor->get_model() == model);
index c10136ec090c2922029e6366a19beff23f702a53..7ccf966ab9962ea57cfb663a1ee791c264c5d3a5 100644 (file)
@@ -70,7 +70,6 @@ QSize SequenceBrowserWidget::sizeHint() const
   return QSize(width, center.height());
 }
 
-
 void SequenceBrowserWidget::clear()
 {
   converted_sequences.clear();
@@ -122,17 +121,17 @@ void SequenceBrowserWidget::copySelectedTracksAsSeqLocation(
 }
 
 void SequenceBrowserWidget::setSequences(
-    const std::vector<boost::shared_ptr<Sequence> >& sequences,
-    boost::shared_ptr<AnnotationColors> cm)
+    const std::vector<SequenceRef >& new_sequences,
+    AnnotationColorsRef cm)
 {
   SequenceBrowser& browser = scrollable_browser->browser();
   clear();
-  for(Mussa::vector_sequence_type::const_iterator seq_i = sequences.begin();
-      seq_i != sequences.end();
+  for(Mussa::vector_sequence_type::const_iterator seq_i = new_sequences.begin();
+      seq_i != new_sequences.end();
       ++seq_i)
   {
     // Blech *(*seq_i) is dereferencing the shared_ptr stored in the iterator.
-    boost::shared_ptr<GlSequence> gs(new GlSequence(*(*seq_i), cm));
+    boost::shared_ptr<GlSequence> gs(new GlSequence(*seq_i, cm));
     converted_sequences.push_back(gs);
     browser.push_sequence(gs);
   }
@@ -142,7 +141,7 @@ void SequenceBrowserWidget::setSequences(
   // connect the text change signals to each other
   SequenceBrowserSidebar::collection left = left_sidebar->descriptions;
   SequenceBrowserSidebar::collection right = right_sidebar->descriptions;
-  for(size_t i = 0; i != sequences.size() and i != right.size(); ++i)
+  for(size_t i = 0; i != new_sequences.size() and i != right.size(); ++i)
   {
     connect(left[i], SIGNAL(nameChanged(const QString &)),
             right[i], SLOT(setName(const QString &)));
index 2b47d412a8945c8dfb7d65e431ec1021433782af..9b4e9c7d74e21706313959d56fd7d45f65504b0a 100644 (file)
@@ -22,6 +22,9 @@ class SequenceBrowserWidget : public QScrollArea
 public:
   SequenceBrowserWidget(boost::shared_ptr<QDir>, QWidget *parent=0);
 
+  //! return our wrapped browser, so we can test it.
+  SequenceBrowser& browser() { return scrollable_browser->browser(); }
+  
   //! return the popup menu for the glcanvas (reference stored internally)
   QMenu *getPopupMenu();
   //! return our fasta copy action (reference stored internally)
@@ -93,6 +96,6 @@ private:
   //! sequences created by a setSequences(vector<Sequences>) call
   /*! I need to save them so i can free them to avoid a memory leak 
    */
-  std::vector<boost::shared_ptr<GlSequence> > converted_sequences;
+  std::vector<GlSequenceRef > converted_sequences;
 };
 #endif
index 73aeb2a9b981ef95e649e404034f24ecc6734a70..5b61c8f7e8a03cad4693197d8850c749163d6997 100644 (file)
@@ -2,4 +2,5 @@
 INCLUDE( TestMacros )
 
 MAKE_QUI_UNITTEST(TestSequenceBrowser)
+MAKE_QUI_UNITTEST(TestSequenceBrowserWidget)
 MAKE_QUI_UNITTEST(TestSequenceDescription)
\ No newline at end of file
diff --git a/qui/seqbrowser/test/TestSequenceBrowserWidget.cpp b/qui/seqbrowser/test/TestSequenceBrowserWidget.cpp
new file mode 100644 (file)
index 0000000..a08933d
--- /dev/null
@@ -0,0 +1,3 @@
+#include "TestSequenceBrowserWidget.hpp"
+
+QTEST_MAIN(TestSequenceBrowserWidget)
diff --git a/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp b/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp
new file mode 100644 (file)
index 0000000..fc82648
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef TESTSEQUENCEBROWSERWIDGET_HPP_
+#define TESTSEQUENCEBROWSERWIDGET_HPP_
+#include <QtGui>
+#include <QVariant>
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+
+#include "alg/sequence.hpp"
+#include "qui/seqbrowser/SequenceBrowserWidget.hpp"
+
+class TestSequenceBrowserWidget : public QObject
+{
+  Q_OBJECT
+
+private slots:
+
+  void testSimpleConstructor() {
+    boost::shared_ptr<QDir> d(new QDir("."));
+    SequenceBrowserWidget *browser = new SequenceBrowserWidget(d);
+  }
+
+  // do we have the right colors?
+  void testChangeMotifColor() {
+    boost::shared_ptr<QDir> d(new QDir("."));
+
+    std::vector<Sequence> motifs;
+    motifs.push_back("AAGG");
+    std::vector<Color> colors1;
+    colors1.push_back(Color(0.0, 0.0, 1.0));
+        
+    MussaRef m(new Mussa);
+    m->append_sequence("AAAAGGGGTTTT");
+    m->set_motifs(motifs, colors1);
+    QVERIFY(m->sequences().size() == 1);
+    QVERIFY(m->sequences()[0]->motifs().size() == 1);
+    QVERIFY(m->sequences()[0]->motifs().front().sequence == "AAGG");
+    QVERIFY(m->colorMapper()->lookup("motif", "AAGG") == colors1[0]);
+
+    SequenceBrowserWidget *browser = new SequenceBrowserWidget(d);
+    browser->setSequences(m->sequences(), m->colorMapper());
+    std::vector<GlSequenceRef> glseqs1(browser->sequences());
+    QVERIFY(glseqs1.size() == 1);
+    QVERIFY(glseqs1[0]->colorMapper() == m->colorMapper());
+    QVERIFY(glseqs1[0]->colorMapper()->lookup("motif", "AAGG") == colors1[0]);
+    
+    std::vector<Color> colors2;
+    colors2.push_back(Color(1.0, 0.0, 0.0));
+    m->set_motifs(motifs, colors2);
+    QVERIFY(m->sequences().size() == 1);
+    QVERIFY(m->sequences()[0]->motifs().size() == 1);
+    QVERIFY(m->sequences()[0]->motifs().front().sequence == "AAGG");
+    QVERIFY(m->colorMapper()->lookup("motif", "AAGG") == colors2[0]);
+    
+    std::vector<GlSequenceRef> glseqs2(browser->sequences());
+    QVERIFY(glseqs2.size() == 1);
+    QVERIFY(glseqs2[0]->colorMapper() == m->colorMapper());
+    QVERIFY(glseqs2[0]->colorMapper()->lookup("motif", "AAGG") == colors2[0]);
+  }
+  
+  // do we have the right colors?
+  void testChangeMotifSequencer() {
+    boost::shared_ptr<QDir> d(new QDir("."));
+
+    std::string aagg("AAGG");
+    std::vector<Sequence> motifs1;
+    motifs1.push_back(aagg);
+    std::vector<Color> colors1;
+    colors1.push_back(Color(0.0, 0.0, 1.0));
+        
+    MussaRef m(new Mussa);
+    m->append_sequence("AAAAGGGG");
+    m->append_sequence("AAAACCCC");
+    m->set_motifs(motifs1, colors1);
+    QVERIFY(m->sequences().size() == 2);
+    QVERIFY(m->sequences()[0]->motifs().size() == 1);
+    QVERIFY(m->sequences()[0]->motifs().front().sequence == aagg);
+    QVERIFY(m->sequences()[1]->motifs().size() == 0);
+    QVERIFY(m->colorMapper()->lookup("motif", aagg) == colors1[0]);
+
+    SequenceBrowserWidget *browser = new SequenceBrowserWidget(d);
+    browser->setSequences(m->sequences(), m->colorMapper());
+    // does the sequence browser have the right motif pattern?
+    std::vector<GlSequenceRef> glseqs1(browser->sequences());
+    QVERIFY(glseqs1.size() == 2);
+    QVERIFY(glseqs1[0]->motifs().size() == 1);
+    QVERIFY(glseqs1[0]->motifs().front().sequence == aagg);
+    QVERIFY(glseqs1[1]->motifs().size() == 0);
+    QVERIFY(glseqs1[0]->colorMapper() == m->colorMapper());
+    QVERIFY(glseqs1[0]->colorMapper()->lookup("motif", aagg) == colors1[0]);
+    
+    std::vector<Sequence> motifs2;
+    std::string aacc("AACC");
+    motifs2.push_back(aacc);
+    m->set_motifs(motifs2, colors1);
+    // did the copy of our sequences in the mussa analysis object get updated?
+    QVERIFY(m->sequences().size() == 2);
+    QVERIFY(m->sequences()[0]->motifs().size() == 0);
+    QVERIFY(m->sequences()[1]->motifs().size() == 1);
+    QVERIFY(m->sequences()[1]->motifs().front().sequence == aacc);
+    QVERIFY(m->colorMapper()->lookup("motif", aacc) == colors1[0]);
+    
+    // did the copy of our sequences in the browser get updated?
+    std::vector<GlSequenceRef> glseqs2(browser->sequences());
+    QVERIFY(glseqs2.size() == 2);
+    QVERIFY(glseqs2[0]->motifs().size() == 0);
+    QVERIFY(glseqs2[1]->motifs().size() == 1);
+    QVERIFY(glseqs2[1]->motifs().front().sequence == aacc);
+    QVERIFY(glseqs2[0]->colorMapper() == m->colorMapper());
+    QVERIFY(glseqs2[0]->colorMapper()->lookup("motif", aacc) == colors1[0]);
+  }  
+};
+#endif /*TESTSEQUENCEBROWSERWIDGET_HPP_*/