1 #include "alg/glseqbrowser.hpp"
2 #include "mussa_exceptions.hpp"
9 GlSeqBrowser::GlSeqBrowser()
11 max_ortho(400.0, 0.0, 600.0, 0.0),
13 viewport_size(600, 400),
21 GlSeqBrowser::GlSeqBrowser(const GlSeqBrowser& gt)
23 max_ortho(gt.max_ortho),
24 cur_ortho(gt.cur_ortho),
25 viewport_size(gt.viewport_size),
26 viewport_center(gt.viewport_center),
27 zoom_level(gt.zoom_level),
28 color_mapper(gt.color_mapper),
29 track_container(gt.track_container)
33 void GlSeqBrowser::initializeGL()
35 glEnable(GL_DEPTH_TEST);
36 glClearColor(1.0, 1.0, 1.0, 0.0);
37 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
38 glShadeModel(GL_FLAT);
41 void GlSeqBrowser::resizeGL(int width, int height)
43 viewport_size.x = width;
44 viewport_size.y = height;
45 glViewport(0, 0, (GLsizei)width, (GLsizei)height);
49 void GlSeqBrowser::paintGL() const
51 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
54 glMatrixMode(GL_PROJECTION);
56 glOrtho(cur_ortho.left, cur_ortho.right,
57 cur_ortho.bottom, cur_ortho.top,
66 void GlSeqBrowser::processSelection(GLuint hits, GLuint buffer[], GLuint bufsize)
70 GLuint consumed_names = 0;
75 GLuint path_index = 0;
76 GLuint pair_key_0 = 0;
77 GLuint pair_key_1 = 0;
79 selectedPaths.clear();
80 selectedTracks.clear();
82 std::cout << "hits = " << hits << std::endl;
83 ptr = (GLuint *) buffer;
86 for (GLuint i=0; i < hits; ++i)
88 if ((i + 5) > bufsize) {
89 std::clog << "*** selection overflow***" << std::endl;
93 z1 = ((float)*ptr++)/0x7fffffff;
94 z2 = ((float)*ptr++)/0x7fffffff;
95 objtype = *ptr++; ++consumed_names;
98 path_index = *ptr++; ++consumed_names;
99 pair_key_0 = *ptr++; ++consumed_names;
100 pair_key_1 = *ptr++; ++consumed_names;
101 if (path_index < path_segments.size()) {
102 segment_key k(pair_key_0, pair_key_1);
103 pair_segment_map::iterator psm_i;
104 psm_i = path_segments[path_index].find(k);
105 if (psm_i != path_segments[path_index].end()) {
106 Segment &seg = psm_i->second;
107 selectedPaths.insert(seg.path_ids.begin(), seg.path_ids.end());
109 // else something else is wrong
111 // something wasn't right
112 clog << "invalid path_index " << path_index
113 << " should have been [0,"<<path_segments.size()
118 objid = *ptr++; ++consumed_names;
119 selectedTracks.insert(objid);
122 cout << "unknown type " << objtype << " ";
123 for(; consumed_names < names; ++consumed_names) {
124 cout << consumed_names << "," << *ptr++ << " ";
133 void GlSeqBrowser::selectRegion(int top, int left, int bottom, int right)
135 GLfloat x_scale = cur_ortho.width()/((float)viewport_size.x);
136 GLfloat y_scale = cur_ortho.height()/((float)viewport_size.y);
137 GLfloat x_left = cur_ortho.left + (left*x_scale);
138 GLfloat x_right = right * x_scale;
141 // woah, someone gave us a rectangle with the origin in the lower left
146 // swap the orientation of canvas coordinates
147 GLfloat y_top = cur_ortho.top-(bottom*y_scale);
148 GLfloat y_bottom = cur_ortho.top - top * y_scale;
149 selectedRegion = rect<float>(y_top, x_left, y_bottom, x_right);
151 // hopefully this will make a buffer big enough to receive
152 // everything being selected
153 //const size_t pathz_count = mussaAnalysis->paths().refined_pathz.size();
154 //const GLuint select_buf_size = 1 + 5 * (pathz_count + sequences.size());
155 const GLuint select_buf_size = 500000;
156 GLuint selectBuf[select_buf_size];
157 glSelectBuffer(select_buf_size, selectBuf);
160 (void)glRenderMode(GL_SELECT);
162 glMatrixMode(GL_PROJECTION);
164 glOrtho(x_left, x_right, y_top, y_bottom, -50.0, 50.0);
165 glMatrixMode(GL_MODELVIEW);
172 hits = glRenderMode(GL_RENDER);
173 processSelection(hits, selectBuf, select_buf_size);
176 float GlSeqBrowser::left() const
178 return max_ortho.left;
181 float GlSeqBrowser::right() const
183 return max_ortho.right;
186 void GlSeqBrowser::setViewportCenter(float x)
188 update_viewport(x, zoom_level);
192 float GlSeqBrowser::viewportLeft() const
194 return cur_ortho.left;
197 float GlSeqBrowser::viewportCenter() const
199 return viewport_center;
202 float GlSeqBrowser::viewportRight() const
204 return cur_ortho.right;
207 float GlSeqBrowser::viewportHeight() const
209 return cur_ortho.top - cur_ortho.bottom;
212 float GlSeqBrowser::viewportWidth() const
214 return cur_ortho.right - cur_ortho.left;
217 void GlSeqBrowser::setZoom(int new_zoom)
219 update_viewport(viewport_center, new_zoom);
220 zoom_level = new_zoom;
223 int GlSeqBrowser::zoom() const
228 void GlSeqBrowser::setColorMapper(AnnotationColors& cm)
233 AnnotationColors& GlSeqBrowser::colorMapper()
238 void GlSeqBrowser::clear()
241 path_segments.clear();
242 track_container.clear();
245 void GlSeqBrowser::push_sequence(const Sequence &s)
247 GlSequence gs(s, color_mapper);
251 void GlSeqBrowser::push_sequence(GlSequence &gs)
255 track_container.push_back(gs);
257 if (track_container.size() > 1)
258 path_segments.push_back(pair_segment_map());
261 const std::vector<GlSequence>& GlSeqBrowser::sequences() const
263 return track_container;
266 void GlSeqBrowser::clear_links()
268 path_segment_map_vector::iterator psmv_i;
269 for(psmv_i = path_segments.begin();
270 psmv_i != path_segments.end();
278 GlSeqBrowser::link(const vector<int>& path, const vector<bool>& rc, int length)
280 if (path.size() < 2) {
281 // should i throw an error instead?
284 if (path.size() != rc.size()) {
285 throw runtime_error("path and reverse compliment must be the same length");
287 vector<int>::const_iterator path_i = path.begin();
288 vector<bool>::const_iterator rc_i = rc.begin();
290 int prev_x = *path_i; ++path_i;
291 bool prev_rc = *rc_i; ++rc_i;
292 while (path_i != path.end() and rc_i != rc.end())
294 segment_key p(prev_x, *path_i);
295 pair_segment_map::iterator found_segment = path_segments[track_i].find(p);
296 if (found_segment == path_segments[track_i].end()) {
298 float y1 = track_container[track_i].y();
299 y1 -= track_container[track_i].height()/2;
300 float y2 = track_container[track_i+1].y();
301 y2 += track_container[track_i+1].height()/2;
303 Segment s(prev_x, y1, *path_i, y2, prev_rc);
304 s.path_ids.insert(pathid);
305 path_segments[track_i][p] = s;
308 found_segment->second.path_ids.insert(pathid);
316 // pathid is reset by push_sequence
320 void GlSeqBrowser::update_viewport(float center, int new_zoom)
322 float max_width = max_ortho.width();
323 // division by zero is a major bummer
327 float new_max_width = max_width / new_zoom;
328 cur_ortho.left = center-new_max_width;
329 cur_ortho.right = center+new_max_width;
332 void GlSeqBrowser::update_layout()
334 typedef std::vector<GlSequence>::iterator glseq_itor_type;
335 float available_height = (float)cur_ortho.top - 2 * (float)border;
336 float max_base_pairs = 0;
337 size_t track_count = track_container.size();
339 if (track_count > 1) {
340 // we have several sequences
341 float track_spacing = available_height / (track_count-1);
342 float y = available_height + (float)border;
343 for(glseq_itor_type seq_i = track_container.begin();
344 seq_i != track_container.end();
345 ++seq_i, y-=track_spacing)
349 if (seq_i->length() > max_base_pairs)
350 max_base_pairs = seq_i->length();
352 } else if (track_count == 1) {
353 // center the single track
354 glseq_itor_type seq_i = track_container.begin();
356 seq_i->setY(viewport_size.x /2);
357 max_base_pairs = seq_i->length();
359 // nothing to do as we're empty
362 max_ortho.right = max_base_pairs + border;
363 max_ortho.left = -border;
364 max_ortho.top = viewport_size.x;
365 max_ortho.bottom = 0;
366 cur_ortho = max_ortho;
367 viewport_center = (cur_ortho.width()/2) + cur_ortho.left;
370 void GlSeqBrowser::draw() const
372 glMatrixMode(GL_MODELVIEW);
374 glPushName(MussaSegment);
376 glLoadName(MussaTrack);
379 // a selection shouldn't have a glName associated with it
383 void GlSeqBrowser::draw_selection() const
385 // draw selection box
387 glDepthMask(GL_FALSE);
389 glColor4f(0.6, 0.6, 0.6, 0.9);
390 glRectf(selectedRegion.left, selectedRegion.top,
391 selectedRegion.right, selectedRegion.bottom);
393 glDepthMask(GL_TRUE);
397 void GlSeqBrowser::draw_tracks() const
399 for(size_t track_i = 0; track_i != track_container.size(); ++track_i)
402 track_container[track_i].draw(cur_ortho.left, cur_ortho.right);
407 void GlSeqBrowser::draw_segments() const
410 // each vector contains path_segment_maps of all the connections
411 // between this track and the next
412 path_segment_map_vector::const_iterator psmv_i;
413 for(psmv_i = path_segments.begin();
414 psmv_i != path_segments.end();
417 path_segment_map_vector::difference_type path_index;
418 path_index = psmv_i - path_segments.begin();
419 // these maps contain the pair index (used so we dont keep drawing the
420 // same segment) and the actual segment structure.
421 pair_segment_map::const_iterator psm_i;
422 for(psm_i = psmv_i->begin();
423 psm_i != psmv_i->end();
426 // grab the index into our segment map
427 const segment_key& key = psm_i->first;
428 // the second element of our map pair is a segment
429 const Segment &s = psm_i->second;
430 // need to do something so we can detect our selection
431 vector<int> selected;
432 set_intersection(selectedPaths.begin(), selectedPaths.end(),
433 s.path_ids.begin(), s.path_ids.end(),
434 back_inserter(selected));
436 if (not s.reversed) {
437 if (selectedPaths.size() == 0 or selected.size() > 0) {
438 glColor3f(1.0, 0.0, 0.0);
440 glColor3f(1.0, 0.8, 0.8);
443 if (selectedPaths.size() == 0 or selected.size() > 0) {
444 glColor3f(0.0, 0.0, 1.0);
446 glColor3f(0.8, 0.8, 1.0);
449 // save the multipart name for our segment
450 glPushName(path_index); glPushName(key.first); glPushName(key.second);
452 glVertex3f(s.start.x, s.start.y, -1);
453 glVertex3f(s.end.x, s.end.y, -1);
456 glPopName(); glPopName(); glPopName();