1 #include "alg/glsequence.hpp"
9 static const float default_height = 12.0;
10 static const float char_pix_per_world_unit = 2.5;
12 GlSequence::GlSequence(const Sequence &s,
13 boost::shared_ptr<AnnotationColors> cm)
17 seq->setDrawable(default_drawable());
20 GlSequence::GlSequence(const GlSequence &s)
22 color_mapper(s.color_mapper)
24 seq->setDrawable(copy_drawable(s.seq->drawable()));
27 GlSequence::GlSequence(const GlSequence *s)
29 color_mapper(s->color_mapper)
31 seq->setDrawable(copy_drawable(s->seq->drawable()));
34 GlSequence::GlSequence(const GlSequenceRef s)
35 : Sequence( (SequenceRef)s ),
36 color_mapper(s->color_mapper)
38 seq->setDrawable(copy_drawable(s->seq->drawable()));
41 GlSequence &GlSequence::operator=(const GlSequence & s)
44 Sequence::operator=(s);
45 seq->setDrawable(copy_drawable(s.seq->drawable()));
46 color_mapper = s.color_mapper;
51 DrawableRef GlSequence::default_drawable()
53 ColorRef c(new Color(0.0, 0.0, 0.0));
54 DrawableRef d(new Drawable(0.0, 0.0, 1.0, default_height, c));
58 DrawableRef GlSequence::copy_drawable(DrawableRef old_d)
60 ColorRef c(old_d->color());
61 DrawableRef d(new Drawable(old_d));
67 SeqSpanRef GlSequence::make_drawable_annotation(
68 Drawable::draw_func_ptr draw,
74 // create all the components of our annotation
75 // (should seq_i-start_i
76 SeqSpanRef empty_seq(seq->subseq(start, count));
77 AnnotationsRef empty_seq_annot(new Annotations(name));
78 DrawableRef drawable(default_drawable());
79 // glue everything to gether
80 drawable->setDrawFunction(draw);
81 drawable->setColor(color);
82 empty_seq->setAnnotations(empty_seq_annot);
83 empty_seq->setDrawable(drawable);
87 void GlSequence::add_annotations_for_defined_sequence(Drawable::draw_func_ptr draw)
89 ColorRef sequence_color(new Color(0.0, 0.0, 0.0));
90 Sequence::const_iterator start_i = begin();
91 Sequence::const_iterator seq_i = begin();
92 Sequence::const_iterator end_i = end();
94 Sequence::const_iterator start_block_i = end();
95 for(; seq_i != end_i; ++seq_i)
97 // need a better set of characters to serch for
98 if (not (*seq_i == 'N' or *seq_i == 'n')) {
99 if (start_block_i == end_i) {
100 start_block_i = seq_i;
103 if (start_block_i != end_i) {
105 size_type start = start_block_i - start_i;
106 size_type count = seq_i - start_block_i;
107 // add the annotation
109 make_drawable_annotation(draw, "sequence", start, count,
112 // reset our counter...
113 start_block_i = end_i;
117 // catch stuff at the end
118 if( start_block_i != end_i ) {
119 size_type start = start_block_i - start_i;
120 size_type count = seq_i - start_block_i;
121 add_annotation(make_drawable_annotation(draw, "sequence", start, count,
127 void GlSequence::update_annotation_draw_function(
129 Drawable::draw_func_ptr draw_func,
133 for(SeqSpanRefList::iterator annot_i = annotation_list->begin();
134 annot_i != annotation_list->end();
137 AnnotationsRef metadata( (*annot_i)->annotations() );
139 if (metadata->has_key("type") and metadata->get("type") == type) {
141 DrawableRef d((*annot_i)->drawable());
143 d = default_drawable();
144 (*annot_i)->setDrawable(d);
146 d->setDrawFunction(draw_func);
152 void GlSequence::setX(float value)
154 seq->drawable()->setX(value);
157 float GlSequence::x() const
159 return seq->drawable()->x();
162 void GlSequence::setY(GLfloat value)
164 seq->drawable()->setY(value);
167 float GlSequence::y() const
169 return seq->drawable()->y();
172 float GlSequence::z() const
174 return seq->drawable()->z();
177 float GlSequence::height() const
179 return seq->drawable()->height();
182 GLfloat GlSequence::right() const
187 Sequence::size_type GlSequence::size() const
189 return Sequence::size();
192 Sequence::size_type GlSequence::leftbase(GLfloat left) const
194 left = ceil(left - x());
197 else if (left > Sequence::size() )
198 return Sequence::size();
200 return (Sequence::size_type)left;
203 Sequence::size_type GlSequence::rightbase(GLfloat right) const
205 right = floor(right) - x();
206 if (right > Sequence::size())
207 return Sequence::size();
211 return (Sequence::size_type)right;
214 Sequence::const_iterator
215 GlSequence::region_begin(GLfloat left, GLfloat right) const
217 if ( leftbase(left) > Sequence::size() or left > right )
218 return Sequence::end();
220 return Sequence::begin() + leftbase(left);
223 Sequence::const_iterator
224 GlSequence::region_end(GLfloat left, GLfloat right) const
226 if ( rightbase(right) > Sequence::size() or left > right )
227 return Sequence::end();
229 return Sequence::begin() + rightbase(right);
232 GlSequence GlSequence::subseq(size_type start, size_type count) const
234 GlSequence new_seq(*this);
235 new_seq.seq = seq->subseq(start, count);
236 // make sure our subseq has a drawable attached to it
237 // perhaps we should figure out correct x,y,z,h coords
238 DrawableRef d(default_drawable());
239 // and default to our current color
242 new_seq.seq->setDrawable(d);
243 copy_children(new_seq, start, count);
248 void GlSequence::setColor(ColorRef &c)
250 seq->drawable()->setColor(c);
253 ColorRef GlSequence::color()
255 return seq->drawable()->color();
258 const ColorRef GlSequence::color() const
260 return seq->drawable()->color();
263 ColorRef GlSequence::default_gene_color()
265 static ColorRef default_color;
266 if (not default_color) {
267 default_color.reset(new Color(0.0, 0.8, 0.0));
269 return default_color;
272 ColorRef GlSequence::default_track_color()
274 static ColorRef default_color;
275 if (not default_color) {
276 default_color.reset(new Color(0.0, 0.0, 0.0));
278 return default_color;
281 ColorRef GlSequence::default_chipseq_color()
283 static ColorRef default_color;
284 if (not default_color) {
285 default_color.reset(new Color(1.0, 0.5, 0.0));
287 return default_color;
290 int GlSequence::get_viewport_width_in_pixels()
293 glGetIntegerv(GL_VIEWPORT, viewport);
294 return viewport[3]; // grab the viewport width
297 GLfloat GlSequence::pixelWidth(GLfloat left, GLfloat right)
299 return pixelWidth(left, right, get_viewport_width_in_pixels());
303 GlSequence::pixelWidth(GLfloat left, GLfloat right, int vp_width)
305 return round((right-left)/vp_width);
308 bool GlSequence::is_sequence_renderable(GLfloat left, GLfloat right)
310 return is_sequence_renderable(left, right, get_viewport_width_in_pixels());
313 bool GlSequence::is_sequence_renderable(GLfloat left,
317 GLfloat world_width = right - left;
318 GLfloat pixels_needed = (char_pix_per_world_unit * world_width);
320 // if the number of pixels taken up by rendering the characters
321 // that'd show up in the current ortho width is less than the window
322 // width we can actually draw something
323 return pixels_needed < viewport_width;
327 void GlSequence::draw(GLfloat left, GLfloat right) const
329 if ( not is_sequence_renderable(left, right) ) {
330 draw_track(left, right);
332 draw_sequence(left, right);
334 draw_annotations(left, right);
337 void GlSequence::draw_box(GLfloat world_left, GLfloat world_right,
338 GLfloat left, GLfloat right,
339 GLfloat height, GLfloat y, GLfloat z,
342 GLfloat pixel_width = pixelWidth(world_left, world_right);
343 GLfloat offset = height/2.0;
344 GLfloat top = y + offset;
345 GLfloat bottom = y - offset;
347 // make our box be at least 1 pixel
348 if ((right-left) < pixel_width) {
349 right = left + pixel_width;
352 glVertex3f(left, top, z);
353 glVertex3f(left, bottom, z);
354 glVertex3f(right, bottom, z);
355 glVertex3f(right, top, z);
359 void GlSequence::draw_track(GLfloat left, GLfloat right) const
361 // draw main sequence track
362 glColor3fv(color()->get());
363 draw_box(left, right, x(), x()+Sequence::size(), height(), y(), 0.0, GL_LINE_LOOP);
365 glColor3f(0.8, 0.8, 0.8);
366 draw_box(left, right, x(), x()+Sequence::size(), height(), y(), 0.0);
369 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
372 GLfloat annotation_z = z() + 10.0;
373 const SeqSpanRefList& annots = Sequence::annotations();
374 const MotifList& motifs = Sequence::motifs();
375 for (SeqSpanRefList::const_iterator annot_itor = annots.begin();
376 annot_itor != annots.end();
379 DrawableRef drawable((*annot_itor)->drawable());
380 if (drawable and drawable->drawFunction()) {
381 assert((*annot_itor)->parent() == seq);
382 drawable->drawFunction()((*annot_itor), left, right);
384 glColor3fv(default_gene_color()->get());
385 draw_box(left, right, x()+(*annot_itor)->start(), x()+(*annot_itor)->stop(),
386 height(), y(), annotation_z);
390 for (MotifList::const_iterator motifs_itor = motifs.begin();
391 motifs_itor != motifs.end();
394 glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
395 draw_box(left, right, x()+motifs_itor->begin, x()+motifs_itor->end,
396 height(), y(), annotation_z+1.0);
400 // this way of drawing characters, came from the red open gl book
402 const int STROKE = 2;
405 typedef struct charpoint {
411 {0, -5, PT}, {2.5, 5, PT}, {5, -5, STROKE},
412 {0.75, -2, PT}, {4.25, -2, END}
416 {2.5, -5, PT}, {2.5,5, STROKE}, {0, 5, PT}, {5, 5, END}
420 {5, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
421 {2, -5, PT}, {3, -5, PT}, {5, -3, STROKE},
422 {2.5, -1, PT}, {5, -1,PT}, {5, -5, END}
426 {4.9, 3, PT}, {3, 5, PT}, {2, 5, PT}, {0, 3, PT}, {0, -3, PT},
427 {2, -5, PT}, {3, -5, PT}, {5, -3, END}
430 CP Xdata[] = {{ 0, 5, PT}, {5, -5,STROKE},{0,-5,PT},{5, 5, END}};
431 CP Ndata[] = {{ 0, -5, PT}, {0, 5, PT}, {5, -5, PT}, {5, 5, END}};
433 //! the maximum width used for a charcter glyph
434 const int max_glyph_width = 5; // unit ( glyph_coord )
436 static void drawLetter(CP *l, GLfloat z)
438 glBegin(GL_LINE_STRIP);
442 glVertex3f(l->x, l->y, z);
445 glVertex3f(l->x, l->y, z);
447 glBegin(GL_LINE_STRIP);
450 glVertex3f(l->x, l->y, z);
455 throw runtime_error("data structure failure");
461 void GlSequence::draw_sequence(GLfloat left, GLfloat right) const
463 // FIXME: basically this needs to be greater than the number of annotations
464 const GLfloat z = 30;
466 glColor3fv(color()->get());
468 Sequence::const_iterator seq_itor = region_begin(left, right);
469 Sequence::const_iterator seq_end = region_end(left, right);
470 Sequence::size_type basepair = 0;
471 const float bp_per_world = 1.0; //( world coord )
472 const float glyph_x_scale = 0.125; // unit = ( world coord / glyph coord )
473 // compute how much space there should be to either size of a letter
474 const float glyph_margin = (bp_per_world - glyph_x_scale * max_glyph_width)
477 assert(seq_end - seq_itor >= 0);
478 while(seq_itor != seq_end)
480 assert ( basepair < Sequence::size() );
482 glTranslatef( x()+leftbase(left) + basepair + glyph_margin, y(), 1.0 );
483 glScalef(glyph_x_scale, 1.0, 1.0);
486 drawLetter(Adata, z);
489 drawLetter(Tdata, z);
492 drawLetter(Gdata, z);
495 drawLetter(Cdata, z);
498 drawLetter(Ndata, z);
501 drawLetter(Xdata, z);
510 bool operator==(const GlSequence &left, const GlSequence &right)
512 return ( (left.x() == right.x()) and
513 (left.y() == right.y()) and
514 (left.z() == right.z()) and
515 (left.height() == right.height()) and
516 (left.color() == right.color()));
519 void draw_narrow_track(SeqSpanRef s, float left, float right)
521 SeqSpanRef parent(s->parent());
522 DrawableRef parent_draw(parent->drawable());
523 float x( (parent_draw) ? parent_draw->x() : 0);
524 float y( (parent_draw) ? parent_draw->y() : 0);
525 float z( (parent_draw) ? parent_draw->z() : 10 );
526 float height( (parent_draw) ? parent_draw->height() : default_height );
527 Color c( (s->drawable()) ? s->drawable()->color() : *GlSequence::default_track_color() );
530 float hsmall = height * 0.25;
531 GlSequence::draw_box(left, right, x+s->start(), x+s->stop(),
535 void draw_chipseq_window(SeqSpanRef s, float left, float right)
537 SeqSpanRef parent(s->parent());
538 DrawableRef parent_draw(parent->drawable());
539 float x( (parent_draw) ? parent_draw->x() : 0);
540 float y( (parent_draw) ? parent_draw->y() : 0);
541 float z( (parent_draw) ? parent_draw->z() : 10 );
542 float height( (parent_draw) ? parent_draw->height() : default_height );
543 Color c( (s->drawable()) ? s->drawable()->color() : *GlSequence::default_track_color() );
546 float hsmall = height * 2.0;
547 GlSequence::draw_box(left, right, x+s->start(), x+s->stop(),
551 void draw_summarized_track(SeqSpanRef s, float left, float right)
553 // if we can see the sequence text (AGCTN), don't draw the black boxes
554 if (not GlSequence::is_sequence_renderable(left, right)) {
555 SeqSpanRef parent(s->parent());
556 DrawableRef parent_draw(parent->drawable());
557 float x( (parent_draw) ? parent_draw->x() : 0);
558 float y( (parent_draw) ? parent_draw->y() : 0);
559 float z( (parent_draw) ? parent_draw->z() : 10 );
560 float height( (parent_draw) ? parent_draw->height() : default_height );
561 Color c( (s->drawable()) ? s->drawable()->color() : *GlSequence::default_track_color() );
563 glColor3fv( c.get() );
564 GlSequence::draw_box(left, right, x+s->start(), x+s->stop(),