From: Diane Trout Date: Wed, 11 Apr 2007 23:47:45 +0000 (+0000) Subject: show where the Ns are X-Git-Url: http://woldlab.caltech.edu/gitweb/?p=mussa.git;a=commitdiff_plain;h=15f9eb9d7ba5ffe32cbe7bc67a9d85b714c27871 show where the Ns are 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. --- diff --git a/alg/drawable.hpp b/alg/drawable.hpp index 97b0105..1ed9169 100644 --- a/alg/drawable.hpp +++ b/alg/drawable.hpp @@ -19,7 +19,8 @@ typedef boost::shared_ptr 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_*/ diff --git a/alg/glseqbrowser.cpp b/alg/glseqbrowser.cpp index d04f6f3..5accb2c 100644 --- a/alg/glseqbrowser.cpp +++ b/alg/glseqbrowser.cpp @@ -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(); diff --git a/alg/glsequence.cpp b/alg/glsequence.cpp index 89150d3..62f8b7a 100644 --- a/alg/glsequence.cpp +++ b/alg/glsequence.cpp @@ -6,6 +6,8 @@ #include using namespace std; +static const float default_height = 12.0; + GlSequence::GlSequence(const Sequence &s, boost::shared_ptr 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 diff --git a/alg/glsequence.hpp b/alg/glsequence.hpp index 39cb36d..190401a 100644 --- a/alg/glsequence.hpp +++ b/alg/glsequence.hpp @@ -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 diff --git a/alg/seq_span.cpp b/alg/seq_span.cpp index 581ef83..bd34e99 100644 --- a/alg/seq_span.cpp +++ b/alg/seq_span.cpp @@ -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) diff --git a/alg/seq_span.hpp b/alg/seq_span.hpp index 1752a7a..cf2723e 100644 --- a/alg/seq_span.hpp +++ b/alg/seq_span.hpp @@ -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_*/ diff --git a/alg/sequence.cpp b/alg/sequence.cpp index 55ff5bf..05ec0a9 100644 --- a/alg/sequence.cpp +++ b/alg/sequence.cpp @@ -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); } diff --git a/alg/sequence.hpp b/alg/sequence.hpp index d476dfe..1714941 100644 --- a/alg/sequence.hpp +++ b/alg/sequence.hpp @@ -228,6 +228,7 @@ public: //! annotate the current sequence with other sequences void find_sequences(std::list::iterator start, std::list::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); diff --git a/alg/test/test_drawable.cpp b/alg/test/test_drawable.cpp index 63d75ef..8319984 100644 --- a/alg/test/test_drawable.cpp +++ b/alg/test/test_drawable.cpp @@ -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 ) diff --git a/alg/test/test_sequence.cpp b/alg/test/test_sequence.cpp index 82ff14b..9faa8d0 100644 --- a/alg/test/test_sequence.cpp +++ b/alg/test/test_sequence.cpp @@ -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 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"); diff --git a/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp b/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp index fc82648..cf60757 100644 --- a/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp +++ b/qui/seqbrowser/test/TestSequenceBrowserWidget.hpp @@ -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 cm(new AnnotationColors); + std::vector 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 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_*/