*/
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) {}
float draw_height;
ColorRef draw_color;
draw_func_ptr draw_func;
-
};
#endif /*DRAWABLE_HPP_*/
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();
#include <stdexcept>
using namespace std;
+static const float default_height = 12.0;
+
GlSequence::GlSequence(const Sequence &s,
boost::shared_ptr<AnnotationColors> cm)
: Sequence(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;
}
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
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);
}
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) {
{
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
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();
{
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);
}
}
(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
//! 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
*/
//! 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;
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;
*/
void draw_sequence(GLfloat, GLfloat) const;
};
+
+void draw_narrow_track(SeqSpanRef ref, float left, float right);
#endif
: 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)
: 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)
strand_type strand_)
: seq_start(0),
seq_count(seq_.length()),
- parent()
+ parent_seq()
{
switch (strand_) {
case PlusStrand:
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;
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;
break;
case UnknownStrand:
case BothStrand:
- seq_strand = parent->strand();
+ seq_strand = parent_seq->strand();
break;
case SingleStrand:
throw sequence_invalid_strand(
}
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");
// 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);
}
}
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);
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)
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
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;
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_*/
: 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)
} 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);
}
//! 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);
BOOST_CHECK_EQUAL(*csp->color(), *black);
}
-void test_draw_func_null(SeqSpanRef r, void *p)
+void test_draw_func_null(SeqSpanRef r, float, float)
{
}
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 )
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 )
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");
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_*/