show where the Ns are
authorDiane Trout <diane@caltech.edu>
Wed, 11 Apr 2007 23:47:45 +0000 (23:47 +0000)
committerDiane Trout <diane@caltech.edu>
Wed, 11 Apr 2007 23:47:45 +0000 (23:47 +0000)
ticket:243

This also tests the new draw function pointer in the drawable class,
as the N marking code uses that functionality to highlight where
the undefined regions are.

There were some problems in making sure that a subseq had the
right parent as I needed the current parent for the proper
draw coordinates.

alg/drawable.hpp
alg/glseqbrowser.cpp
alg/glsequence.cpp
alg/glsequence.hpp
alg/seq_span.cpp
alg/seq_span.hpp
alg/sequence.cpp
alg/sequence.hpp
alg/test/test_drawable.cpp
alg/test/test_sequence.cpp
qui/seqbrowser/test/TestSequenceBrowserWidget.hpp

index 97b01059259587015db5bda8c87ff69dc5d87d9a..1ed9169fda9cd8ddc51f9d4337c5dd7d2a13701b 100644 (file)
@@ -19,7 +19,8 @@ typedef boost::shared_ptr<Drawable> DrawableRef;
  */ 
 class Drawable {
 public:
-  typedef void (*draw_func_ptr)(SeqSpanRef, void *);
+  // render our SeqSpanRef in the region between left/right
+  typedef void (*draw_func_ptr)(SeqSpanRef, float left, float right);
   
   Drawable() : 
     draw_x(0), draw_y(0), draw_z(0), draw_height(0), draw_color(new Color), draw_func(0) {}
@@ -65,6 +66,5 @@ protected:
   float draw_height;
   ColorRef draw_color;
   draw_func_ptr draw_func;
-
 };
 #endif /*DRAWABLE_HPP_*/
index d04f6f3a199feb9cfaab21ad74996ee9d5ff24d0..5accb2cd0dc2bc89342b977c6e810a66409d5306 100644 (file)
@@ -355,6 +355,9 @@ void GlSeqBrowser::push_sequence(GlSequence gs)
 void GlSeqBrowser::push_sequence(GlSequenceRef gs)
 {
   GlSequenceRef new_gs(new GlSequence(gs));
+  // mark where the undefined sequence is
+  new_gs->add_annotations_for_undefined_sequence(draw_narrow_track);
+  
   clear_links();
   track_container.push_back(new_gs);
   update_layout();
index 89150d3a0068aba3cf1d169cf6b322ab4c88bacf..62f8b7a83e6ac1d9a0254d97a2cca5a1d1264b60 100644 (file)
@@ -6,6 +6,8 @@
 #include <stdexcept>
 using namespace std;
 
+static const float default_height = 12.0;
+
 GlSequence::GlSequence(const Sequence &s, 
                        boost::shared_ptr<AnnotationColors> cm) 
   : Sequence(s),
@@ -53,7 +55,7 @@ GlSequence &GlSequence::operator=(const GlSequence & s)
 DrawableRef GlSequence::default_drawable()
 {
   ColorRef c(new Color(0.0, 0.0, 0.0));
-  DrawableRef d(new Drawable(0.0, 0.0, 1.0, 12.0, c));
+  DrawableRef d(new Drawable(0.0, 0.0, 1.0, default_height, c));
   return d;
 }
 
@@ -90,7 +92,6 @@ void GlSequence::add_annotations_for_undefined_sequence(Drawable::draw_func_ptr
   Sequence::const_iterator end_i = end();
   
   Sequence::const_iterator start_block_i = end();
-  
   for(; seq_i != end_i; ++seq_i)
   {
     // need a better set of characters to serch for
@@ -237,13 +238,13 @@ int GlSequence::get_viewport_width_in_pixels()
   return viewport[3]; // grab the viewport width
 }
 
-GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right) const
+GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right)
 {
   return pixelWidth(left, right, get_viewport_width_in_pixels());
 }
 
 GLfloat
-GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width) const
+GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width)
 {
   return round((right-left)/vp_width);
 }
@@ -279,12 +280,12 @@ void GlSequence::draw(GLfloat left, GLfloat right) const
 
 void GlSequence::draw_box(GLfloat world_left, GLfloat world_right,
                           GLfloat left, GLfloat right, 
-                          GLfloat height, GLfloat z) const
+                          GLfloat height, GLfloat y, GLfloat z)
 {
   GLfloat pixel_width = pixelWidth(world_left, world_right);
   GLfloat offset = height/2.0;
-  GLfloat top = y() + offset;
-  GLfloat bottom = y() - offset;
+  GLfloat top = y + offset;
+  GLfloat bottom = y - offset;
   
   // make our box be at least 1 pixel
   if ((right-left) < pixel_width) {
@@ -302,7 +303,7 @@ void GlSequence::draw_track(GLfloat left, GLfloat right) const
 {
   glColor3fv(color()->get());
   // draw main sequence track
-  draw_box(left, right, x(), x()+Sequence::size(), height(), 0.0);
+  draw_box(left, right, x(), x()+Sequence::size(), height(), y(), 0.0);
 }
 
 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
@@ -315,9 +316,15 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
        annot_itor != annots.end();
        ++annot_itor)
   {
-    glColor3f(0.0, 0.8, 0.0);
-    draw_box(left, right, x()+(*annot_itor)->start(), x()+(*annot_itor)->stop(), 
-             height(), annotation_z);
+    DrawableRef drawable((*annot_itor)->drawable());
+    if (drawable and drawable->drawFunction()) {
+      assert((*annot_itor)->parent() == seq);
+      drawable->drawFunction()((*annot_itor), left, right); 
+    } else {
+      glColor3f(0.0, 0.8, 0.0);
+      draw_box(left, right, x()+(*annot_itor)->start(), x()+(*annot_itor)->stop(), 
+               height(), y(), annotation_z);
+    }
   }
   // if motifs?
   for (MotifList::const_iterator motifs_itor = motifs.begin();
@@ -326,7 +333,7 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
   {
     glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
     draw_box(left, right, x()+motifs_itor->begin, x()+motifs_itor->end, 
-             height(), annotation_z+1.0);
+             height(), y(), annotation_z+1.0);
   }
 }
 
@@ -449,3 +456,22 @@ bool operator==(const GlSequence &left, const GlSequence &right)
            (left.color() == right.color()));
 }
 
+void draw_narrow_track(SeqSpanRef s, float left, float right)
+{
+  SeqSpanRef parent(s->parent());
+  DrawableRef parent_draw(parent->drawable());
+  float x( (parent_draw) ? parent_draw->x() : 0);
+  float y( (parent_draw) ? parent_draw->y() : 0);
+  float z( (parent_draw) ? parent_draw->z() : 10 );
+  float height( (parent_draw) ? parent_draw->height() : default_height ); 
+
+  glColor3f(1.0, 1.0, 1.0);
+  // offset to middle of the top (+) or bottom (-) quarter 
+  float yoffset = height * 5.0/8.0; //(1/2 + 1/8)
+  // height of a quarter
+  float hsmall = height * 1.0/4.0;
+  GlSequence::draw_box(left, right, x+s->start(), x+s->stop(), 
+                       hsmall, y, z+10);
+  //GlSequence::draw_box(left, right, x+s->start(), x+s->stop(), 
+  //                     hsmall, y-yoffset, z+10);
+}
\ No newline at end of file
index 39cb36d53e076ca971c9b080a69783d68b7471bf..190401a956644ddc3aed36af42857be5bba7715f 100644 (file)
@@ -59,6 +59,11 @@ public:
   //! return our annotation color mapper
   AnnotationColorsRef colorMapper() { return color_mapper; }
 
+  //! draw a from left to right +/- height/2
+  static
+  void draw_box(GLfloat world_left, GLfloat world_right, 
+                GLfloat left, GLfloat right, GLfloat height,
+                GLfloat y, GLfloat z);
   //! draw a track 
   /*! left and right are the edges of the current viewport
    */
@@ -83,10 +88,12 @@ public:
   //! return a subsequence as a GlSequence (instead of a Sequence subsequence)
   GlSequence subseq(size_type start, size_type count) const;
   
+  //! Return the pixel width of the opengl viewport.
+  static int get_viewport_width_in_pixels();
   //! how big is a pixel in world coordinats
-  GLfloat pixelWidth(GLfloat, GLfloat) const;
+  static GLfloat pixelWidth(GLfloat, GLfloat);
   //! how big is a pixel in world coordinats (specifying viewport size)
-  GLfloat pixelWidth(GLfloat, GLfloat, int) const;
+  static GLfloat pixelWidth(GLfloat, GLfloat, int);
 
   //! are we close enough that it would make sense to view the base pairs?
   bool is_sequence_renderable(GLfloat left, GLfloat right) const;
@@ -113,10 +120,6 @@ protected:
     size_type start,
     size_type count);
 
-  //! Return the pixel width of the opengl viewport.
-  static int get_viewport_width_in_pixels();
-  //! draw a from left to right +/- height/2
-  void draw_box(GLfloat world_left, GLfloat world_right, GLfloat left, GLfloat right, GLfloat height, GLfloat z) const;
   //! draw sequence as a bar
   void draw_track(GLfloat, GLfloat) const;
   void draw_annotations(GLfloat, GLfloat) const;
@@ -125,4 +128,6 @@ protected:
    */
   void draw_sequence(GLfloat, GLfloat) const;
 };
+
+void draw_narrow_track(SeqSpanRef ref, float left, float right);
 #endif
index 581ef830c43711e0ca5423502eb50faac791bb07..bd34e991cb03d9e6c7be488cc56eb8d99966bdc0 100644 (file)
@@ -9,7 +9,7 @@ SeqSpan::SeqSpan(const SeqSpan &o)
   : seq(o.seq),
     seq_start(o.seq_start),
     seq_count(o.seq_count),
-    parent(o.parent),
+    parent_seq(o.parent_seq),
     rc_seq(o.rc_seq),
     seq_annotations(o.seq_annotations),
     seq_drawable(o.seq_drawable)
@@ -20,7 +20,7 @@ SeqSpan::SeqSpan(const SeqSpan *p)
   : seq(p->seq),
     seq_start(p->seq_start),
     seq_count(p->seq_count),
-    parent(p->parent),
+    parent_seq(p->parent_seq),
     rc_seq(p->rc_seq),
     seq_annotations(p->seq_annotations),
     seq_drawable(p->seq_drawable) 
@@ -32,7 +32,7 @@ SeqSpan::SeqSpan(const std::string &seq_,
                  strand_type strand_)
   : seq_start(0),
     seq_count(seq_.length()),
-    parent()
+    parent_seq()
 {
   switch (strand_) {
   case PlusStrand:
@@ -55,7 +55,7 @@ SeqSpan::SeqSpan(const SeqSpanRef parent_,
                  strand_type strand_) 
   : seq(parent_->seq),
     seq_start(parent_->seq_start + start_),
-    parent(parent_)    
+    parent_seq(parent_)    
 {
   if (count_ == npos)
     seq_count = parent_->seq_count;
@@ -71,15 +71,15 @@ SeqSpan::SeqSpan(const SeqSpanRef parent_,
     seq_strand = strand_;
   break;
   case SameStrand:
-    if (parent) {
-      seq_strand = parent->strand();
+    if (parent_seq) {
+      seq_strand = parent_seq->strand();
     } else {
       throw sequence_invalid_strand("SameStrand is undefined with no parent");
     }
   break;
   case OppositeStrand:
-    if (parent) {
-      switch (parent->strand()) {
+    if (parent_seq) {
+      switch (parent_seq->strand()) {
       case PlusStrand:
         seq_strand = MinusStrand;
       break;
@@ -88,7 +88,7 @@ SeqSpan::SeqSpan(const SeqSpanRef parent_,
       break;
       case UnknownStrand:
       case BothStrand:
-        seq_strand = parent->strand();
+        seq_strand = parent_seq->strand();
       break;
       case SingleStrand:
         throw sequence_invalid_strand(
@@ -103,8 +103,8 @@ SeqSpan::SeqSpan(const SeqSpanRef parent_,
     }
   break;
   case SingleStrand:
-    if (parent) {
-      if (parent->strand() == SingleStrand) {
+    if (parent_seq) {
+      if (parent_seq->strand() == SingleStrand) {
         seq_strand = SingleStrand;
       } else {
         throw  sequence_invalid_strand("Can't change single strandedness");
@@ -122,8 +122,8 @@ SeqSpan::SeqSpan(const SeqSpanRef parent_,
   // If our parent is on the minus strand, we need to adjust the start
   // and count to look like we're selecting from the right side of the 
   // parent sequence (AKA the start of the minus strand)
-  if (parent and parent->strand() == MinusStrand) {
-    seq_start = parent->start() + parent->size() - (start_ + seq_count);
+  if (parent_seq and parent_seq->strand() == MinusStrand) {
+    seq_start = parent_seq->start() + parent_seq->size() - (start_ + seq_count);
   }
 }
 
@@ -135,7 +135,7 @@ SeqSpan &SeqSpan::operator=(const SeqSpan& s)
     seq = s.seq;
     seq_start = s.seq_start;
     seq_count = s.seq_count;
-    parent = s.parent;
+    parent_seq = s.parent_seq;
     rc_seq = s.rc_seq;
     //seq_annotations.reset(s.seq_annotations);
     //seq_drawable.reset(s.seq_drawable);
@@ -326,32 +326,32 @@ void SeqSpan::setStop(SeqSpan::size_type v)
 
 SeqSpan::size_type SeqSpan::parentStart() const
 {
-  if (!parent) {
+  if (!parent_seq) {
     // no parent
     return start();
   } else {
-    return start() - parent->start();
+    return start() - parent_seq->start();
   } 
 }
 
 void SeqSpan::setParentStart(SeqSpan::size_type v)
 {
-  setStart(parent->start() + v);
+  setStart(parent_seq->start() + v);
 }
 
 SeqSpan::size_type SeqSpan::parentStop() const
 {
-  if (!parent) {
+  if (!parent_seq) {
     // no parent
     return stop();
   } else {
-    return stop() - parent->start();
+    return stop() - parent_seq->start();
   }
 }
 
 void SeqSpan::setParentStop(SeqSpan::size_type v)
 {
-  setStop(parent->start() + v);
+  setStop(parent_seq->start() + v);
 }
 
 SeqSpanRef SeqSpan::subseq(size_type start, size_type count, strand_type strand)
index 1752a7ad160ea862008c7117f08e6a195dc40a39..cf2723ea928d7bfc80034bba4d3d811940b226bb 100644 (file)
@@ -123,7 +123,8 @@ public:
   size_type parentStop() const;
   //! set stop position relative to parent sequence
   void setParentStop(size_type);
-  size_type parentSize() const { return (parent) ? parent->size() : size(); }
+  size_type parentSize() const { return (parent_seq) ? parent_seq->size() : size(); }
+  SeqSpanRef parent() { return parent_seq; }
   
 
   //! return a subsequence, copying over any appropriate annotation
@@ -158,7 +159,7 @@ protected:
   strand_type seq_strand;
   
   //! keep a reference to who our parent span is 
-  SeqSpanRef parent;
+  SeqSpanRef parent_seq;
   
   //! hold a reverse complement version of our sequence if needed
   SeqStringRef rc_seq;  
@@ -179,7 +180,7 @@ protected:
     ar & BOOST_SERIALIZATION_NVP(seq_start);
     ar & BOOST_SERIALIZATION_NVP(seq_count);
     ar & BOOST_SERIALIZATION_NVP(seq_strand);
-    ar & BOOST_SERIALIZATION_NVP(parent);
+    ar & BOOST_SERIALIZATION_NVP(parent_seq);
   }
 };
 #endif /*SEQ_SPAN_HPP_*/
index 55ff5bf91bb575f9322102fafc78d4259ac1bd62..05ec0a928dfc63390421f87927444b4179332063 100644 (file)
@@ -123,9 +123,22 @@ Sequence::Sequence(const SequenceRef o)
   : seq(new SeqSpan(o->seq)),
     header(o->header),
     species(o->species),
-    annotation_list(o->annotation_list),
+    annotation_list(new SeqSpanRefList),
     motif_list(o->motif_list)
 {
+  // copy over the annotations in the other sequence ref, 
+  // attaching them to our current sequence ref
+  for(SeqSpanRefList::const_iterator annot_i = o->annotation_list->begin();
+      annot_i != o->annotation_list->end();
+      ++annot_i)
+  {
+    size_type annot_begin= (*annot_i)->start();
+    size_type annot_count = (*annot_i)->size();
+    
+    SeqSpanRef new_annot(seq->subseq(annot_begin, annot_count));
+    new_annot->setAnnotations((*annot_i)->annotations());
+    annotation_list->push_back(new_annot);
+  }  
 }
 
 Sequence::Sequence(const SeqSpanRef& seq_ref)
@@ -566,8 +579,7 @@ void Sequence::copy_children(Sequence &new_seq, size_type start, size_type count
       } else {
         annot_end = count;
       }
-
-      SeqSpanRef new_annot(seq->subseq(annot_begin, annot_end));
+      SeqSpanRef new_annot(new_seq.seq->subseq(annot_begin, annot_end));
       new_annot->setAnnotations((*annot_i)->annotations());
       new_seq.annotation_list->push_back(new_annot);
     }
index d476dfef2b9a3347a9706a57d295073c32c8f663..17149415c622c14899c2a6b8f8959c01db36906d 100644 (file)
@@ -228,6 +228,7 @@ public:
   //! annotate the current sequence with other sequences
   void find_sequences(std::list<Sequence>::iterator start, 
                      std::list<Sequence>::iterator end);
+  SeqSpanRef seqspan() { return seq; }
   
   void save(boost::filesystem::fstream &save_file);
   void load_museq(boost::filesystem::path load_file_path, int seq_num);
index 63d75efdd8be802dd4aa018886b69496251b750c..8319984a9b57ec42f7af9c85b401258574bd8156 100644 (file)
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE( drawable_copyref_constructor )
   BOOST_CHECK_EQUAL(*csp->color(), *black); 
 }
 
-void test_draw_func_null(SeqSpanRef r, void *p)
+void test_draw_func_null(SeqSpanRef r, float, float)
 {
 }
 
@@ -82,10 +82,10 @@ BOOST_AUTO_TEST_CASE( drawable_null_draw_func )
   BOOST_CHECK_EQUAL(bsp->drawFunction(), test_draw_func_null);
 }
 
-void test_draw_func_find_drawable(SeqSpanRef r, void *p)
+void test_draw_func_find_drawable(SeqSpanRef ref, float l, float r)
 {
-  BOOST_REQUIRE(r->drawable());
-  BOOST_REQUIRE_EQUAL(r->drawable()->drawFunction(), test_draw_func_find_drawable);
+  BOOST_REQUIRE(ref->drawable());
+  BOOST_REQUIRE_EQUAL(ref->drawable()->drawFunction(), test_draw_func_find_drawable);
 }
 
 BOOST_AUTO_TEST_CASE( test_drawable_find_drawable )
index 82ff14be6c1ff40c6d9ce1155def83c0c5e4dda7..9faa8d069c156376ce945202527664b9955d47e6 100644 (file)
@@ -586,6 +586,22 @@ BOOST_AUTO_TEST_CASE( annotation_load_no_species_name )
   BOOST_CHECK_EQUAL( annots[0]->annotations()->get("type"), "type");
 }
 
+// when we do a subsequence (or something that calls copy_children)
+// the annotations need to be updated to have the right parent
+BOOST_AUTO_TEST_CASE( update_annotations_seqref )
+{
+  Sequence s1("AAAAGGGG");
+  s1.add_annotation("A", "A", 0, 4);
+  BOOST_CHECK_EQUAL(s1.annotations().size(), 1);
+  BOOST_CHECK_EQUAL(s1.seqspan(), s1.annotations().front()->parent() );
+  
+  Sequence subseq1(s1.subseq(2,4));
+  BOOST_CHECK_EQUAL(subseq1.annotations().size(), 1);
+  BOOST_CHECK_EQUAL(subseq1.annotations().front()->parentStart(), 0 );
+  BOOST_CHECK_EQUAL(subseq1.annotations().front()->parentStop(), 2 );
+  BOOST_CHECK_EQUAL(subseq1.seqspan(), subseq1.annotations().front()->parent() );
+}
+
 // ticket:83 when you try to load a sequence from a file that doesn't
 // have fasta headers it crashes. 
 BOOST_AUTO_TEST_CASE( sequence_past_end ) 
@@ -840,22 +856,22 @@ BOOST_AUTO_TEST_CASE( subseq_annotation_test )
   BOOST_REQUIRE_EQUAL( annots_list.size(), 4 );
   
   std::vector<SeqSpanRef> annots(annots_list.begin(), annots_list.end());
-  BOOST_CHECK_EQUAL( annots[0]->start(),  0);
+  BOOST_CHECK_EQUAL( annots[0]->parentStart(),  0);
   BOOST_CHECK_EQUAL( annots[0]->size(),  5);
   BOOST_REQUIRE( annots[0]->annotations() );
   BOOST_CHECK_EQUAL( annots[0]->annotations()->name(), "0-10");
 
-  BOOST_CHECK_EQUAL( annots[1]->start(), 5);
-  BOOST_CHECK_EQUAL( annots[1]->size(), 10);
+  BOOST_CHECK_EQUAL( annots[1]->parentStart(), 5);
+  BOOST_CHECK_EQUAL( annots[1]->size(), 5);
   BOOST_REQUIRE( annots[1]->annotations() );
   BOOST_CHECK_EQUAL( annots[1]->annotations()->name(), "10-20");
 
-  BOOST_CHECK_EQUAL( annots[2]->start(), 0);
+  BOOST_CHECK_EQUAL( annots[2]->parentStart(), 0);
   BOOST_CHECK_EQUAL( annots[2]->size(), 10);
   BOOST_REQUIRE( annots[2]->annotations() );
   BOOST_CHECK_EQUAL( annots[2]->annotations()->name(), "0-20");
 
-  BOOST_CHECK_EQUAL( annots[3]->start(), 3);
+  BOOST_CHECK_EQUAL( annots[3]->parentStart(), 3);
   BOOST_CHECK_EQUAL( annots[3]->size(),  7);
   BOOST_REQUIRE( annots[3]->annotations() );
   BOOST_CHECK_EQUAL( annots[3]->annotations()->name(), "8-12");
index fc82648f2babda60187e9ae5fd5aa32150c7d6b0..cf60757b82b1e226134c42144b66cded96711486 100644 (file)
@@ -112,5 +112,36 @@ private slots:
     QVERIFY(glseqs2[0]->colorMapper() == m->colorMapper());
     QVERIFY(glseqs2[0]->colorMapper()->lookup("motif", aacc) == colors1[0]);
   }  
+  
+  void testAnnotationsInTwoBrowsers()
+  {
+    // Make sure that our annotations parent is pointing to the 
+    // most right seqspan parent
+    boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
+    std::vector<SequenceRef> seqs;
+    SequenceRef seq0(new Sequence("AAAAGGGG"));
+    seq0->add_annotation("A","A", 0, 4);
+    seqs.push_back(seq0);
+    SequenceRef seq1(new Sequence("GGGGTTTT"));
+    seqs.push_back(seq1);
+
+    QVERIFY(seq0->annotations().size() == 1);
+    QVERIFY(seq0->seqspan() == seq0->annotations().front()->parent() );
+    
+    boost::shared_ptr<QDir> d(new QDir("."));
+    SequenceBrowserWidget *b1 = new SequenceBrowserWidget(d);
+    b1->setSequences(seqs, cm );
+    QVERIFY( b1->sequences().size() == 2);
+    QVERIFY( b1->sequences()[0]->annotations().size() == 1 );
+    QVERIFY( b1->sequences()[0]->seqspan() == 
+             b1->sequences()[0]->annotations().front()->parent() );
+
+    SequenceBrowserWidget *b2 = new SequenceBrowserWidget(d);
+    b2->setSequences(seqs, cm);
+    
+    QVERIFY( b2->sequences()[0]->annotations().size() == 1 );
+    QVERIFY( b2->sequences()[0]->seqspan() == 
+             b2->sequences()[0]->annotations().front()->parent() );
+  }
 };
 #endif /*TESTSEQUENCEBROWSERWIDGET_HPP_*/