#include <stdexcept>
using namespace std;
-GlSequence::GlSequence(boost::shared_ptr<Sequence> s,
+static const float default_height = 12.0;
+
+GlSequence::GlSequence(const Sequence &s,
boost::shared_ptr<AnnotationColors> 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_drawable_annotation(
+ Drawable::draw_func_ptr draw,
+ std::string name,
+ size_type start,
+ size_type count,
+ ColorRef color)
{
- 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(name));
+ DrawableRef drawable(default_drawable());
+ // glue everything to gether
+ drawable->setDrawFunction(draw);
+ drawable->setColor(color);
+ empty_seq->setAnnotations(empty_seq_annot);
+ empty_seq->setDrawable(drawable);
+ return empty_seq;
}
-GLfloat GlSequence::right() const
+void GlSequence::add_annotations_for_defined_sequence(Drawable::draw_func_ptr draw)
{
- return size()+seq_x;
+ ColorRef sequence_color(new Color(0.0, 0.0, 0.0));
+ 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 (not (*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_drawable_annotation(draw, "sequence", start, count,
+ sequence_color)
+ );
+ // 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_drawable_annotation(draw, "sequence", start, count,
+ sequence_color)
+ );
+ }
+}
+
+void GlSequence::update_annotation_draw_function(
+ std::string type,
+ Drawable::draw_func_ptr draw_func,
+ ColorRef color
+)
+{
+ for(SeqSpanRefList::iterator annot_i = annotation_list->begin();
+ annot_i != annotation_list->end();
+ ++annot_i)
+ {
+ AnnotationsRef metadata( (*annot_i)->annotations() );
+
+ if (metadata->has_key("type") and metadata->get("type") == type) {
+ // we should update
+ DrawableRef d((*annot_i)->drawable());
+ if (!d) {
+ d = default_drawable();
+ (*annot_i)->setDrawable(d);
+ }
+ d->setDrawFunction(draw_func);
+ d->setColor(color);
+ }
+ }
+}
+
+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);
}
-GLfloat GlSequence::y() const
+float GlSequence::y() const
{
- return seq_y;
+ return seq->drawable()->y();
}
-GLfloat GlSequence::height() const
+float GlSequence::z() const
{
- return seq_height;
+ return seq->drawable()->z();
+}
+
+float GlSequence::height() const
+{
+ return seq->drawable()->height();
+}
+
+GLfloat GlSequence::right() const
+{
+ 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
+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
{
- 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)
{
- if ( rightbase(right) > seq->size() or left > right )
- return seq->end();
- else
- return seq->begin() + rightbase(right);
+ seq->drawable()->setColor(c);
}
+ColorRef GlSequence::color()
+{
+ return seq->drawable()->color();
+}
-//! set default track draw color
-void GlSequence::setColor(Color &c)
+const ColorRef GlSequence::color() const
{
- drawColor = c;
+ return seq->drawable()->color();
}
-//! get default track draw color
-Color GlSequence::color()
+ColorRef GlSequence::default_gene_color()
{
- return drawColor;
+ static ColorRef default_color;
+ if (not default_color) {
+ default_color.reset(new Color(0.0, 0.8, 0.0));
+ }
+ return default_color;
}
+ColorRef GlSequence::default_track_color()
+{
+ static ColorRef default_color;
+ if (not default_color) {
+ default_color.reset(new Color(0.0, 0.0, 0.0));
+ }
+ return default_color;
+}
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);
}
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,
+ GLint primitive)
{
- 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) {
right = left + pixel_width;
}
- glBegin(GL_QUADS);
+ glBegin(primitive);
glVertex3f(left, top, z);
glVertex3f(left, bottom, z);
glVertex3f(right, bottom, z);
void GlSequence::draw_track(GLfloat left, GLfloat right) const
{
- glColor3fv(drawColor.get());
// draw main sequence track
- draw_box(left, right, seq_x, seq_x+seq->size(), seq_height, 0.0);
+ glColor3fv(color()->get());
+ draw_box(left, right, x(), x()+Sequence::size(), height(), y(), 0.0, GL_LINE_LOOP);
+
+ glColor3f(0.8, 0.8, 0.8);
+ 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<annot>& annots = seq->annotations();
- const std::list<motif>& motifs = seq->motifs();
- for (std::list<annot>::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 {
+ glColor3fv(default_gene_color()->get());
+ draw_box(left, right, x()+(*annot_itor)->start(), x()+(*annot_itor)->stop(),
+ height(), y(), annotation_z);
+ }
}
// if motifs?
- for (std::list<motif>::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;
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);
// 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);
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 );
+ Color c( (s->drawable()) ? s->drawable()->color() : *GlSequence::default_track_color() );
+ glColor3fv(c.get());
+
+ float hsmall = height * 0.25;
+ GlSequence::draw_box(left, right, x+s->start(), x+s->stop(),
+ hsmall, y, z+10);
+}
+
+void draw_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 );
+ Color c( (s->drawable()) ? s->drawable()->color() : *GlSequence::default_track_color() );
+
+ glColor3fv( c.get() );
+ GlSequence::draw_box(left, right, x+s->start(), x+s->stop(),
+ height, y, z+10);
+}