X-Git-Url: http://woldlab.caltech.edu/gitweb/?a=blobdiff_plain;f=alg%2Fglsequence.cpp;h=6c8b12b80410418e2e8bc2c0ec537a574724283a;hb=fd0de7877ef325b4922bfe9968d85607a681751d;hp=de262d461ce9dc283079842c9da879ac55fd0186;hpb=38dc74d72ea09e5a2c9acc3fd72c231849c82166;p=mussa.git diff --git a/alg/glsequence.cpp b/alg/glsequence.cpp index de262d4..6c8b12b 100644 --- a/alg/glsequence.cpp +++ b/alg/glsequence.cpp @@ -6,149 +6,230 @@ #include using namespace std; -GlSequence::GlSequence(boost::shared_ptr s, +static const float default_height = 12.0; + +GlSequence::GlSequence(const Sequence &s, boost::shared_ptr cm) - : seq(s), - seq_x(0.0), - seq_y(0.0), - seq_z(1.0), - seq_height(12.0), + : Sequence(s), color_mapper(cm), - drawColor(0.0, 0.0, 0.0), char_pix_per_world_unit(2.5) { + seq->setDrawable(default_drawable()); } GlSequence::GlSequence(const GlSequence &s) - : seq(s.seq), - seq_x(s.seq_x), - seq_y(s.seq_y), - seq_z(s.seq_z), - seq_height(s.seq_height), + : Sequence(s), color_mapper(s.color_mapper), - drawColor(s.drawColor), char_pix_per_world_unit(s.char_pix_per_world_unit) { + seq->setDrawable(copy_drawable(s.seq->drawable())); +} + +GlSequence::GlSequence(const GlSequence *s) + : Sequence(s), + color_mapper(s->color_mapper), + char_pix_per_world_unit(s->char_pix_per_world_unit) +{ + seq->setDrawable(copy_drawable(s->seq->drawable())); +} + +GlSequence::GlSequence(const GlSequenceRef s) + : Sequence( (SequenceRef)s ), + color_mapper(s->color_mapper), + char_pix_per_world_unit(s->char_pix_per_world_unit) +{ + seq->setDrawable(copy_drawable(s->seq->drawable())); } GlSequence &GlSequence::operator=(const GlSequence & s) { if (this != &s) { - seq = s.seq; - seq_x = s.seq_x; - seq_y = s.seq_y; - seq_z = s.seq_z; - seq_height = s.seq_height; + Sequence::operator=(s); + seq->setDrawable(copy_drawable(s.seq->drawable())); color_mapper = s.color_mapper; - drawColor = s.drawColor; assert(char_pix_per_world_unit == s.char_pix_per_world_unit); } return *this; } -const Sequence& GlSequence::sequence() const +DrawableRef GlSequence::default_drawable() { - return *seq; + ColorRef c(new Color(0.0, 0.0, 0.0)); + DrawableRef d(new Drawable(0.0, 0.0, 1.0, default_height, c)); + return d; } -void GlSequence::setX(GLfloat value) +DrawableRef GlSequence::copy_drawable(DrawableRef old_d) { - seq_x = value; + ColorRef c(old_d->color()); + DrawableRef d(new Drawable(old_d)); + // use the same color + d->setColor(c); + return d; } -GLfloat GlSequence::x() const +SeqSpanRef GlSequence::make_undefined_sequence_annotation( + Drawable::draw_func_ptr draw, + size_type start, + size_type count) { - return seq_x; + // create all the components of our annotation + // (should seq_i-start_i + SeqSpanRef empty_seq(seq->subseq(start, count)); + AnnotationsRef empty_seq_annot(new Annotations("null")); + DrawableRef drawable(default_drawable()); + // glue everything to gether + drawable->setDrawFunction(draw); + empty_seq->setAnnotations(empty_seq_annot); + empty_seq->setDrawable(drawable); + return empty_seq; } -GLfloat GlSequence::right() const +void GlSequence::add_annotations_for_undefined_sequence(Drawable::draw_func_ptr draw) { - return size()+seq_x; + Sequence::const_iterator start_i = begin(); + Sequence::const_iterator seq_i = begin(); + 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 + if (*seq_i == 'N' or *seq_i == 'n') { + if (start_block_i == end_i) { + start_block_i = seq_i; + } + } else { + if (start_block_i != end_i) { + // we got one. + size_type start = start_block_i - start_i; + size_type count = seq_i - start_block_i; + // add the annotation + add_annotation(make_undefined_sequence_annotation(draw, start, count)); + // reset our counter... + start_block_i = end_i; + } + } + } + // catch stuff at the end + if( start_block_i != end_i ) { + size_type start = start_block_i - start_i; + size_type count = seq_i - start_block_i; + add_annotation(make_undefined_sequence_annotation(draw, start, count)); + } +} + + +void GlSequence::setX(float value) +{ + seq->drawable()->setX(value); +} + +float GlSequence::x() const +{ + return seq->drawable()->x(); } void GlSequence::setY(GLfloat value) { - seq_y = value; + seq->drawable()->setY(value); +} + +float GlSequence::y() const +{ + return seq->drawable()->y(); +} + +float GlSequence::z() const +{ + return seq->drawable()->z(); } -GLfloat GlSequence::y() const +float GlSequence::height() const { - return seq_y; + return seq->drawable()->height(); } -GLfloat GlSequence::height() const +GLfloat GlSequence::right() const { - return seq_height; + return size()+x(); } GLfloat GlSequence::size() const { - return seq->size(); + return Sequence::size(); } Sequence::size_type GlSequence::leftbase(GLfloat left) const { - left = ceil(left - seq_x); + left = ceil(left - x()); if (left < 0) return 0; - else if (left > seq->size() ) - return seq->size(); + else if (left > Sequence::size() ) + return Sequence::size(); else return (Sequence::size_type)left; } Sequence::size_type GlSequence::rightbase(GLfloat right) const { - right = floor(right) - seq_x; - if (right > seq->size()) - return seq->size(); + right = floor(right) - x(); + if (right > Sequence::size()) + return Sequence::size(); else if ( right < 0) return 0; else return (Sequence::size_type)right; } -Sequence::const_iterator GlSequence::sequence_begin() const -{ - return seq->begin(); -} - -Sequence::const_iterator GlSequence::sequence_end() const -{ - return seq->end(); -} - Sequence::const_iterator -GlSequence::sequence_begin(GLfloat left, GLfloat right) const +GlSequence::region_begin(GLfloat left, GLfloat right) const { - if ( leftbase(left) > seq->size() or left > right ) - return seq->end(); + if ( leftbase(left) > Sequence::size() or left > right ) + return Sequence::end(); else - return seq->begin() + leftbase(left); + return Sequence::begin() + leftbase(left); } Sequence::const_iterator -GlSequence::sequence_end(GLfloat left, GLfloat right) const +GlSequence::region_end(GLfloat left, GLfloat right) const { - if ( rightbase(right) > seq->size() or left > right ) - return seq->end(); + if ( rightbase(right) > Sequence::size() or left > right ) + return Sequence::end(); else - return seq->begin() + rightbase(right); + return Sequence::begin() + rightbase(right); } +GlSequence GlSequence::subseq(size_type start, size_type count) const +{ + GlSequence new_seq(*this); + new_seq.seq = seq->subseq(start, count); + // make sure our subseq has a drawable attached to it + // perhaps we should figure out correct x,y,z,h coords + DrawableRef d(default_drawable()); + // and default to our current color + ColorRef c(color()); + d->setColor(c); + new_seq.seq->setDrawable(d); + copy_children(new_seq, start, count); + + return new_seq; +} -//! set default track draw color -void GlSequence::setColor(Color &c) +void GlSequence::setColor(ColorRef &c) { - drawColor = c; + seq->drawable()->setColor(c); } -//! get default track draw color -Color GlSequence::color() +ColorRef GlSequence::color() { - return drawColor; + return seq->drawable()->color(); } +const ColorRef GlSequence::color() const +{ + return seq->drawable()->color(); +} int GlSequence::get_viewport_width_in_pixels() { @@ -157,13 +238,13 @@ int GlSequence::get_viewport_width_in_pixels() return viewport[3]; // grab the viewport width } -GLfloat GlSequence::get_pixel_width(GLfloat left, GLfloat right) const +GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right) { - return get_pixel_width(left, right, get_viewport_width_in_pixels()); + return pixelWidth(left, right, get_viewport_width_in_pixels()); } GLfloat -GlSequence::get_pixel_width(GLfloat left, GLfloat right, int vp_width) const +GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width) { return round((right-left)/vp_width); } @@ -199,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 = get_pixel_width(world_left, world_right); + GLfloat pixel_width = pixelWidth(world_left, world_right); GLfloat offset = height/2.0; - GLfloat top = seq_y + offset; - GLfloat bottom = seq_y - offset; + GLfloat top = y + offset; + GLfloat bottom = y - offset; // make our box be at least 1 pixel if ((right-left) < pixel_width) { @@ -220,37 +301,43 @@ void GlSequence::draw_box(GLfloat world_left, GLfloat world_right, void GlSequence::draw_track(GLfloat left, GLfloat right) const { - glColor3fv(drawColor.get()); + glColor3fv(color()->get()); // draw main sequence track - draw_box(left, right, seq_x, seq_x+seq->size(), seq_height, 0.0); + draw_box(left, right, x(), x()+Sequence::size(), height(), y(), 0.0); } void GlSequence::draw_annotations(GLfloat left, GLfloat right) const { // draw annotations - GLfloat annotation_z = seq_z + 10.0; - const std::list& annots = seq->annotations(); - const std::list& motifs = seq->motifs(); - for (std::list::const_iterator annot_itor = annots.begin(); + GLfloat annotation_z = z() + 10.0; + const SeqSpanRefList& annots = Sequence::annotations(); + const MotifList& motifs = Sequence::motifs(); + for (SeqSpanRefList::const_iterator annot_itor = annots.begin(); annot_itor != annots.end(); ++annot_itor) { - glColor3f(0.0, 0.8, 0.0); - draw_box(left, right, seq_x+annot_itor->begin, seq_x+annot_itor->end, - seq_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 (std::list::const_iterator motifs_itor = motifs.begin(); + for (MotifList::const_iterator motifs_itor = motifs.begin(); motifs_itor != motifs.end(); ++motifs_itor) { glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get()); - draw_box(left, right, seq_x+motifs_itor->begin, seq_x+motifs_itor->end, - seq_height, annotation_z+1.0); + draw_box(left, right, x()+motifs_itor->begin, x()+motifs_itor->end, + height(), y(), annotation_z+1.0); } - } +// this way of drawing characters, came from the red open gl book const int PT = 1; const int STROKE = 2; const int END =3; @@ -283,6 +370,9 @@ CP Cdata[] = { CP Xdata[] = {{ 0, 5, PT}, {5, -5,STROKE},{0,-5,PT},{5, 5, END}}; CP Ndata[] = {{ 0, -5, PT}, {0, 5, PT}, {5, -5, PT}, {5, 5, END}}; +//! the maximum width used for a charcter glyph +const int max_glyph_width = 5; // unit ( glyph_coord ) + static void drawLetter(CP *l, GLfloat z) { glBegin(GL_LINE_STRIP); @@ -313,19 +403,24 @@ void GlSequence::draw_sequence(GLfloat left, GLfloat right) const // FIXME: basically this needs to be greater than the number of annotations const GLfloat z = 30; glLineWidth(1); - glColor3fv(drawColor.get()); + glColor3fv(color()->get()); - Sequence::const_iterator seq_itor = sequence_begin(left, right); - Sequence::const_iterator seq_end = sequence_end(left, right); + Sequence::const_iterator seq_itor = region_begin(left, right); + Sequence::const_iterator seq_end = region_end(left, right); Sequence::size_type basepair = 0; + const float bp_per_world = 1.0; //( world coord ) + const float glyph_x_scale = 0.125; // unit = ( world coord / glyph coord ) + // compute how much space there should be to either size of a letter + const float glyph_margin = (bp_per_world - glyph_x_scale * max_glyph_width) + / 2.0; assert(seq_end - seq_itor >= 0); while(seq_itor != seq_end) { - assert ( basepair < seq->size() ); + assert ( basepair < Sequence::size() ); glPushMatrix(); - glTranslatef( seq_x+leftbase(left) + basepair, seq_y, 1.0 ); - glScalef(0.1, 1.0, 1.0); + glTranslatef( x()+leftbase(left) + basepair + glyph_margin, y(), 1.0 ); + glScalef(glyph_x_scale, 1.0, 1.0); switch (*seq_itor) { case 'A': case 'a': drawLetter(Adata, z); @@ -354,10 +449,24 @@ void GlSequence::draw_sequence(GLfloat left, GLfloat right) const bool operator==(const GlSequence &left, const GlSequence &right) { - return ( (left.seq_x == right.seq_x) and - (left.seq_y == right.seq_y) and - (left.seq_z == right.seq_z) and - (left.seq_height == right.seq_height) and - (left.drawColor == right.drawColor)); + return ( (left.x() == right.x()) and + (left.y() == right.y()) and + (left.z() == right.z()) and + (left.height() == right.height()) and + (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); + float hsmall = height * 3.0/4.0; + GlSequence::draw_box(left, right, x+s->start(), x+s->stop(), + hsmall, y, z+10); +} \ No newline at end of file