X-Git-Url: http://woldlab.caltech.edu/gitweb/?a=blobdiff_plain;f=alg%2Fglsequence.cpp;h=6c8b12b80410418e2e8bc2c0ec537a574724283a;hb=fd0de7877ef325b4922bfe9968d85607a681751d;hp=62896aaea62674578cdb167848048f2baa13ef9b;hpb=198f7c18fd0b5fa84528e9b28a84269c3a856cc4;p=mussa.git diff --git a/alg/glsequence.cpp b/alg/glsequence.cpp index 62896aa..6c8b12b 100644 --- a/alg/glsequence.cpp +++ b/alg/glsequence.cpp @@ -6,157 +6,258 @@ #include using namespace std; -GlSequence::GlSequence(const Sequence &s) - : seq(s), - seq_x(0.0), - seq_y(0.0), - seq_z(1.0), - seq_height(12.0), - drawColor(0.0, 0.0, 0.0), - char_pix_per_world_unit(5.0) -{ -} - -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), - drawColor(s.drawColor), +static const float default_height = 12.0; + +GlSequence::GlSequence(const Sequence &s, + boost::shared_ptr cm) + : Sequence(s), + color_mapper(cm), + char_pix_per_world_unit(2.5) +{ + seq->setDrawable(default_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 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) { - const_cast(seq) = s.seq; - seq_x = s.seq_x; - seq_y = s.seq_y; - seq_z = s.seq_z; - seq_height = s.seq_height; - drawColor = s.drawColor; + Sequence::operator=(s); + seq->setDrawable(copy_drawable(s.seq->drawable())); + color_mapper = s.color_mapper; 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; +} + +void GlSequence::add_annotations_for_undefined_sequence(Drawable::draw_func_ptr draw) +{ + 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(); +} + +float GlSequence::height() const +{ + return seq->drawable()->height(); } -GLfloat GlSequence::y() const +GLfloat GlSequence::right() const { - return seq_y; + return size()+x(); } -GLfloat GlSequence::length() const +GLfloat GlSequence::size() const { - return seq.size(); + return Sequence::size(); } Sequence::size_type GlSequence::leftbase(GLfloat left) const { - assert (seq_x == 0); - left = ceil(left); - if (left < seq_x) + left = ceil(left - x()); + if (left < 0) return 0; + else if (left > Sequence::size() ) + return Sequence::size(); else return (Sequence::size_type)left; } Sequence::size_type GlSequence::rightbase(GLfloat right) const { - assert (seq_x == 0); - right = floor(right); - if (right > seq.size()) - return seq.size(); - else + 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 +Sequence::const_iterator +GlSequence::region_begin(GLfloat left, GLfloat right) const { - return seq.begin(); + if ( leftbase(left) > Sequence::size() or left > right ) + return Sequence::end(); + else + return Sequence::begin() + leftbase(left); } -Sequence::const_iterator GlSequence::sequence_end() const +Sequence::const_iterator +GlSequence::region_end(GLfloat left, GLfloat right) const { - return seq.end(); + if ( rightbase(right) > Sequence::size() or left > right ) + return Sequence::end(); + else + return Sequence::begin() + rightbase(right); } -Sequence::const_iterator -GlSequence::sequence_begin(GLfloat left, GLfloat right) const +GlSequence GlSequence::subseq(size_type start, size_type count) const { - // the following code will be wrong when sequences can be slid around - // so make sure we break. - assert (seq_x == 0); - - if ( leftbase(left) > seq.size() or left > right ) - return seq.end(); - else - return seq.begin() + leftbase(left); + 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; } -Sequence::const_iterator -GlSequence::sequence_end(GLfloat left, GLfloat right) const +void GlSequence::setColor(ColorRef &c) { - // the following code will be wrong when sequences can be slid around - // so make sure we break. - assert (seq_x == 0); + seq->drawable()->setColor(c); +} - if ( rightbase(right) > seq.size() or left > right ) - return seq.end(); - else - return seq.begin() + rightbase(right); +ColorRef GlSequence::color() +{ + return seq->drawable()->color(); } +const ColorRef GlSequence::color() const +{ + return seq->drawable()->color(); +} -//! set default track draw color -void GlSequence::setColor(Color &c) +int GlSequence::get_viewport_width_in_pixels() { - drawColor = c; + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + return viewport[3]; // grab the viewport width } -//! get default track draw color -Color GlSequence::color() +GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right) { - return drawColor; + return pixelWidth(left, right, get_viewport_width_in_pixels()); } +GLfloat +GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width) +{ + return round((right-left)/vp_width); +} -int GlSequence::get_viewport_pixel_width() +bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right) const { - int viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - return viewport[3]; // grab the viewport width + return is_sequence_renderable(left, right, get_viewport_width_in_pixels()); } bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right, int viewport_width) const { - // if called with default argument, go get the viewable width - if (viewport_width == -1) { - viewport_width = get_viewport_pixel_width(); - } GLfloat world_width = right - left; GLfloat pixels_needed = (char_pix_per_world_unit * world_width); @@ -177,13 +278,19 @@ void GlSequence::draw(GLfloat left, GLfloat right) const draw_annotations(left, right); } -void GlSequence::draw_box(GLfloat left, GLfloat right, - GLfloat height, GLfloat z) const +void GlSequence::draw_box(GLfloat world_left, GLfloat world_right, + GLfloat left, GLfloat right, + GLfloat height, GLfloat y, GLfloat z) { + 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) { + right = left + pixel_width; + } glBegin(GL_QUADS); glVertex3f(left, top, z); glVertex3f(left, bottom, z); @@ -191,29 +298,46 @@ void GlSequence::draw_box(GLfloat left, GLfloat right, glVertex3f(right, top, z); glEnd(); } + void GlSequence::draw_track(GLfloat left, GLfloat right) const { - glColor3fv(drawColor.get()); + glColor3fv(color()->get()); // draw main sequence track - draw_box(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 - glLineWidth(seq_height); - GLfloat annotation_z = seq_z + 1.0; - std::list annots = seq.annotations(); - 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, ++annotation_z) + ++annot_itor) { - glColor3f(0.0, 0.5, 0.0); - draw_box(seq_x+annot_itor->start, 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 (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, 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; @@ -246,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); @@ -275,20 +402,25 @@ 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(0.3); - glColor3fv(drawColor.get()); + glLineWidth(1); + 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( 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); @@ -317,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