NCBI C++ ToolKit
trace_graph.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: trace_graph.cpp 46023 2021-01-21 13:48:43Z grichenk $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a 'United States Government Work' under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Andrey Yazhuk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistd.hpp>
34 
37 
38 #include <gui/opengl/glhelpers.hpp>
39 #include <gui/opengl/irender.hpp>
40 #include <gui/types.hpp>
41 
42 #include <math.h>
43 
44 #include <memory>
45 
46 
49 
50 
52 : m_SignalStyle(eCurve),
53  m_ConfGraphState(eExpanded),
54  m_SignalGraphState(eExpanded),
55  m_bReverseColors(true)
56 {
57 }
58 
61 {
62  m_SignalStyle = orig.m_SignalStyle;
63  m_ConfGraphState = orig.m_ConfGraphState;
64  m_SignalGraphState = orig.m_SignalGraphState;
65  return *this;
66 }
67 
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 /// CTraceGraph
71 
72 const static int kGradColors = 32;
73 
74 CTraceGraph::CTraceGraph(const CBioseq_Handle& handle, bool b_neg_strand)
75 : m_DataProxy(handle, b_neg_strand),
76  m_Data(NULL),
77  m_Font(CGlTextureFont::eFontFace_Helvetica, 10),
78  m_TextColor(0.6f, 0.6f, 0.6f)
79 {
80 
81 }
82 
83 
85 {
86  Destroy();
87 }
88 
89 
90 // vertical spacing between graph area border and graph
91 static const int kGraphOffsetY = 1;
92 
93 static const int kConfGraphPrefH = 24;
94 static const int kSignalGraphPrefH = 40;
95 static const int kCollapsedGraphH = 11;
96 
97 
99 {
100  switch(m_Props.m_ConfGraphState) {
103  case CTraceGraphProperties::eHidden: return 0;
104  }
105  return 0;
106 }
107 
108 
110 {
111  switch(m_Props.m_SignalGraphState) {
114  case CTraceGraphProperties::eHidden: return 0;
115  }
116  return 0;
117 }
118 
119 
121 {
122 }
123 
124 
125 static const int kTextOff = 2;
126 
128 {
129  TVPUnit h = 0;
130  if(m_Data) {
131  h = x_GetConfGraphH();
132  h += x_GetSignalGraphH();
133  h += 2;
134  } else {
135  // Don't display meaningless text signs
136  // h = (TVPUnit) m_Font.TextHeight() + 2 * kTextOff;
137  }
138  return TVPPoint(0, h);
139 }
140 
141 
142 bool CTraceGraph::NeedTooltip(CGlPane& /*pane*/, int vp_x, int vp_y)
143 {
144  _VERIFY(m_VPRect.PtInRect(vp_x, vp_y));
145 
146  return false; //TODO
147 }
148 
149 
151 {
152  return "";
153 }
154 
155 
157 {
158  return (m_Data != NULL);
159 }
160 
161 
163 {
165  if(m_Data) {
167 
168  bool b_ch = m_Data->GetSamplesCount() > 0;
171 
172  m_vSignalColors.resize(4 * kGradColors);
173  float k = 1.0f / kGradColors;
174 
175  for( int j = 0; j < kGradColors; j++ ) {
176  float v = 1.0f - k * j;
177  m_vSignalColors[j] = CRgbaColor(1.0f, v, v); //red
178  m_vSignalColors[kGradColors + j] = CRgbaColor(v, 1.0f, v); //green
179  m_vSignalColors[2 * kGradColors + j] = CRgbaColor(v, v, 1.0f); //blue
180  m_vSignalColors[3 * kGradColors + j] = CRgbaColor(0.5f * (1 + v), v, 0.5f * (1 + v)); //purple
181  }
182 
183  m_Data->CalculateMax();
184  return true;
185  } else return false;
186 }
187 
188 
190 {
191  if(m_Data) {
192  delete m_Data;
193  m_Data = NULL;
194 
195  m_vSignalColors.clear();
196  }
197 }
198 
199 
201 {
202  return &m_Props;
203 }
204 
205 
207 {
208  CTraceGraphProperties* trace_props =
209  dynamic_cast<CTraceGraphProperties*>(props);
210  if(trace_props) {
211  m_Props = *trace_props;
212  }
213 }
214 
215 
217 {
219 }
220 
221 
223 {
225 }
226 
227 
228 // renders both Confidence graph and Chromatograms
230 {
231  //LOG_POST(Info << "CTraceGraph::Render() ");
232  //LOG_POST(Info << " Viewport " << m_VPRect.ToString() << "\n Visible " << m_ModelRect.ToString());
233 
234  CGlAttrGuard AttrGuard(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_HINT_BIT
235  | GL_LINE_SMOOTH | GL_POLYGON_MODE | GL_LINE_BIT);
236 
237  if( ! m_Data) {
238  // Don't display meaningless text signs
239  // x_RenderText(pane);
240  return;
241  }
242 
243  IRender& gl = GetGl();
244 
245  int conf_h = x_GetConfGraphH();
246  int sig_h = x_GetSignalGraphH();
247  int top_y = int(m_ModelRect.Top() - pane.GetOffsetY());
248 
249  pane.OpenOrtho();
250 
251  unique_ptr<IAlnSegmentIterator> it_1(it.Clone());
252  x_RenderContour(pane, top_y, sig_h, conf_h + sig_h, *it_1); // render background
253 
255  if(pane.GetScaleX() < 1.0) { // render signal graph
256  if(m_Props.m_SignalStyle == CTraceGraphProperties::eCurve) { // render curves
257  gl.Enable(GL_BLEND);
258  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
259 
260  gl.Enable(GL_LINE_SMOOTH);
261  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
262  gl.LineWidth(0.5);
263 
264  unique_ptr<IAlnSegmentIterator> it_3(it.Clone());
265  x_RenderSignalGraph(pane, top_y, sig_h, *it_3);
266  } else { // render intensity bands
267  pane.Close();
268  pane.OpenPixels();
269 
270  gl.Disable(GL_BLEND);
271  gl.Disable(GL_LINE_SMOOTH);
272  gl.LineWidth(1.0);
273 
274  unique_ptr<IAlnSegmentIterator> it_4(it.Clone());
275  x_RenderIntensityGraphs(pane, top_y, sig_h, *it_4);
276 
277  pane.Close();
278  pane.OpenOrtho();
279  }
280  }
281  top_y += sig_h;
282  }
283 
285  // render confidence graph
286  unique_ptr<IAlnSegmentIterator> it_2(it.Clone());
287  x_RenderConfGraph(pane, top_y, conf_h, *it_2);
288  }
289 
290  pane.Close();
291 }
292 
293 
295 {
296  pane.OpenPixels();
297 
298  IRender& gl = GetGl();
299 
300  TVPRect rc = m_VPRect;
301  rc.Inflate(-kTextOff, -kTextOff);
302 
303  gl.ColorC(m_TextColor);
304  m_Font.TextOut(rc.Left(), rc.Bottom(), rc.Right(), rc.Top(),
305  "Trace Graph - no data available", IGlFont::eAlign_Left);
306 
307  pane.Close();
308 }
309 
310 // Functor for coordinate translation align <->seq
312 {
313 public:
316  {
317  }
318 
319  void Init(const TSignedSeqRange& seq_range,
320  const TSignedSeqRange& aln_range, bool negative)
321  {
322  m_SeqRange = &seq_range;
323  m_AlnRange = &aln_range;
326  }
328  {
330 
331  TSignedSeqPos seq_off = seq_pos - m_SeqRange->GetFrom();
332  if(m_bNegative) {
333  return m_AlnRange->GetTo() - seq_off;
334  } else return seq_off + m_AlnRange->GetFrom();
335  }
336  inline double GetAlnPosFromSeqPos(double seq_pos)
337  {
339 
340  double seq_off = seq_pos - m_SeqRange->GetFrom();
341  if(m_bNegative) {
342  return m_AlnRange->GetTo() - seq_off;
343  } else return seq_off + m_AlnRange->GetFrom();
344  }
346  {
348 
349  TSignedSeqPos aln_off = aln_pos - m_AlnRange->GetFrom();
350  if(m_bNegative) {
351  return m_SeqRange->GetTo() - aln_off;
352  } else return aln_off + m_SeqRange->GetFrom();
353  }
354  inline double GetSeqPosFromAlnPos(double aln_pos)
355  {
357 
358  double aln_off = aln_pos - m_AlnRange->GetFrom();
359  if(m_bNegative) {
360  return m_SeqRange->GetTo() - aln_off;
361  } else return aln_off + m_SeqRange->GetFrom();
362  }
363 protected:
367 };
368 
369 
370 void CTraceGraph::x_RenderContour(CGlPane& pane, int y, int top_h, int total_h,
372 {
373  IRender& gl = GetGl();
374 
375  gl.Disable(GL_BLEND);
376  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
377  gl.Color3d(0.9, 0.9, 0.9);
378 
379  TModelUnit offset_x = pane.GetOffsetX();
380  TModelUnit y1 = y;
381  TModelUnit y2 = y + top_h - 1;
382  TModelUnit y3 = y + top_h + 1;
383  TModelUnit y4 = y + total_h - 1;
384 
386  SChunkTranslator trans;
387 
388  // iterate by segments
389  for( ; it; ++it ) {
390  const IAlnSegment& seg = *it;
391  if(seg.IsAligned()) {
392  TSignedSeqRange ch_range = seg.GetRange();
393  const TSignedSeqRange& ch_aln_range = seg.GetAlnRange();
394  trans.Init(ch_range, ch_aln_range, m_Data->IsNegative());
395 
396  ch_range.IntersectWith(gr_range);
397 
398  if(ch_range.NotEmpty()) {
399  double x1 = trans.GetAlnPosFromSeqPos(ch_range.GetFrom()) - offset_x;
400  double x2 = trans.GetAlnPosFromSeqPos(ch_range.GetTo()) - offset_x;
401  if(x1 > x2) {
402  swap(x1, x2);
403  }
404  x2 += 1.0;
405  gl.Rectd(x1, y1, x2, y2);
406  gl.Rectd(x1, y3, x2, y4);
407  }
408  }
409  }
410 }
411 
412 
413 const static float kEps = 0.000001f; // precision for float point comparisions
414 
415 
416 // renders confidence graph
417 void CTraceGraph::x_RenderConfGraph(CGlPane& pane, int y, int h,
418  IAlnSegmentIterator& it_seg)
419 {
420  const TVPRect& rc_vp = pane.GetViewport();
421  const TModelRect rc_vis = pane.GetVisibleRect();
422 
423  IRender& gl = GetGl();
424 
425  gl.Disable(GL_BLEND);
426  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
427 
428 
429  TModelUnit amp = 0.0;
430  // guard against the situation where confidence data is not available
431  // or fails to load
432  if (m_Data->GetMaxConfidence() != 0.0) {
433  amp = ((TModelUnit) h - 2 * kGraphOffsetY -1)
435  }
436 
437  TModelUnit base_y = y + kGraphOffsetY;
438  TModelUnit scale_x = pane.GetScaleX();
439 
440  TSignedSeqPos gr_from = m_Data->GetSeqFrom();
441  TSignedSeqPos gr_to = m_Data->GetSeqTo();
442 
443  SChunkTranslator trans;
444 
445  bool b_average = (scale_x > 0.3);
446  if(b_average) {
447  pane.Close();
448  pane.OpenPixels();
449 
450  //calculate visible range in seq coords
451  TVPUnit range_pix_start = rc_vp.Left();
452  TVPUnit range_pix_end = rc_vp.Right();
453 
454  TModelUnit left = rc_vis.Left();
455  scale_x = pane.GetScaleX();
456  TModelUnit top_y = rc_vp.Bottom() - (y + kGraphOffsetY);
457 
458  gl.Begin(GL_LINES);
459 
460  bool it_seg_moved = true;
461  const IAlnSegment* seg = NULL;
462 
463  TModelUnit pos_pix_left, pos_pix_right;
464 
465  TSignedSeqPos from = -1, to = -2;
466  TSignedSeqPos pos = gr_from, pos_inc = 1;
467  double v = 0, v_min = 0, v_max = 0;
468 
469  TModelUnit ch_pix_end = range_pix_start - 1;
470 
471  for( int pix = range_pix_start;
472  pix <= range_pix_end && it_seg && pos <= gr_to; ) { // iterate by pixels
473  bool b_first = true;
474 
475  // if segment ends before pixel
476  if(it_seg_moved) {
477  // advance segment
478  seg = &*it_seg;
479  if(seg->IsAligned()) {
480  const TSignedSeqRange& ch_range = seg->GetRange();
481  const TSignedSeqRange& ch_aln_range = seg->GetAlnRange();
482 
483  trans.Init(ch_range, ch_aln_range, m_Data->IsNegative());
484 
485  // calculate intersection of the segment in seq_coords with graph range
486  from = max(ch_range.GetFrom(), gr_from);
487  to = min(ch_range.GetTo(), gr_to);
488 
489  // clip with visible align range (expanding integer clip)
490  TSignedSeqPos vis_from = trans.GetSeqPosFromAlnPos((TSignedSeqPos) floor(rc_vis.Left()));
491  TSignedSeqPos vis_to = trans.GetSeqPosFromAlnPos((TSignedSeqPos) ceil(rc_vis.Right()));
492  if(vis_to < vis_from) {
494  swap(vis_from, vis_to);
495  }
496  from = max(from, vis_from);
497  to = min(to, vis_to);
498  if(m_Data->IsNegative()) {
499  ch_pix_end = range_pix_start + (trans.GetAlnPosFromSeqPos(from) + 1 - left) / scale_x;
500  pos = to;
501  pos_inc = -1;
502  } else {
503  ch_pix_end = range_pix_start + (trans.GetAlnPosFromSeqPos(to) + 1 - left) / scale_x;
504  pos = from;
505  pos_inc = 1;
506  }
507  }
508  it_seg_moved = false;
509  }
510 
511  if(seg->IsAligned()) {
512  TSignedSeqPos aln_pos = trans.GetAlnPosFromSeqPos(pos);
513  pos_pix_left = range_pix_start + (aln_pos - left) / scale_x;
514  pos_pix_right = pos_pix_left + 1 / scale_x;
515 
516  pos_pix_left = max((TModelUnit) pix, pos_pix_left);
517 
518  _ASSERT(pos_pix_left >= pix);
519 
520  while(pos >= from && pos <= to && pos_pix_left < pix + 1) {
521  // calculate overlap with pixel and integrate
522  v = amp * m_Data->GetConfidence(pos);
523 
524  v_min = b_first ? v : min(v_min, v);
525  v_max = b_first ? v : max(v_max, v);
526  b_first = false;
527 
528  if(pos_pix_right < pix +1) {
529  pos +=pos_inc; // advance to next pos
530  aln_pos = trans.GetAlnPosFromSeqPos(pos);
531  pos_pix_left = range_pix_start + (aln_pos - left) / scale_x;
532  pos_pix_right = pos_pix_left + 1 / scale_x;
533  } else break;
534  }
535  }
536  if(ch_pix_end < pix + 1) {
537  ++it_seg;
538  it_seg_moved = true;
539  } else {
540  if(seg->IsAligned()) {
541  gl.Color3d(0.0f, 0.5f, 0.0f);
542  gl.Vertex2d(pix, top_y);
543  gl.Vertex2d(pix, top_y - v_min);
544 
545  gl.Color3d(0.0f, 0.75f, 0.25f);
546  gl.Vertex2d(pix, top_y - v_min);
547  gl.Vertex2d(pix, top_y - v_max);
548 
549  }
550  pix++;
551  v = v_min = v_max = 0;
552  }
553  }
554  gl.End();
555  } else { // render without averaging
557 
558  TModelUnit offset_x = pane.GetOffsetX();
559  gl.Color3d(0.0f, 0.5f, 0.0f); //###
560 
561  for( ; it_seg; ++it_seg ) {
562  const IAlnSegment& seg = *it_seg;
563  if(seg.IsAligned()) {
564  const TSignedSeqRange& ch_range = seg.GetRange();
565  const TSignedSeqRange& ch_aln_range = seg.GetAlnRange();
566  trans.Init(ch_range, ch_aln_range, m_Data->IsNegative());
567 
568  TSignedSeqPos from = max(gr_from, ch_range.GetFrom());
569  TSignedSeqPos to = min(gr_to, ch_range.GetTo());
570 
571  for( TSignedSeqPos pos = from; pos <= to; pos ++ ) {
572  double v = m_Data->GetConfidence(pos);
573  v *= amp;
574  TSignedSeqPos aln_pos = trans.GetAlnPosFromSeqPos(pos);
575  double x = aln_pos - offset_x;
576  gl.Rectd(x , base_y, x + 1.0, base_y + v);
577  }
578  }
579  }
580  }
581 }
582 
583 const static int kIntBandSpace = 1;
584 
585 void CTraceGraph::x_RenderSignalGraph(CGlPane& pane, int y, int h,
587 {
588  IRender& gl = GetGl();
589 
590  CTraceData::TSignalValue MaxSignal = 0;
591  for( int ch = CTraceData::eA; ch <= CTraceData::eG; ch++ ) {
592  MaxSignal = max(MaxSignal, m_Data->GetMax( (CTraceData::EChannel) ch));
593  }
594  TModelUnit amp = ((TModelUnit) (h - 2 * kGraphOffsetY)) / MaxSignal;
595  int bottom_y = y + (h - 1) - kGraphOffsetY;
596 
597  for( int i_ch = 0; i_ch < 4; i_ch++ ) { // for every channel (i_ch - channel index)
598  int ch_index = (m_Props.m_bReverseColors && m_Data->IsNegative()) ? (i_ch ^ 2) : i_ch;
599  int ch = CTraceData::eA + ch_index;
600 
601  const CTraceData::TPositions& positions = m_Data->GetPositions();
602 
604  const CTraceData::TValues& values = m_Data->GetValues(channel);
605 
606  gl.ColorC(m_vSignalColors[kGradColors * (i_ch + 1) -1]);
607  gl.PolygonMode(GL_FRONT_AND_BACK, GL_LINE);
608 
610 
611  unique_ptr<IAlnSegmentIterator> p_it_1(it.Clone());
612  for( IAlnSegmentIterator& it_1(*p_it_1); it_1; ++it_1 ) {
613  if(it_1->IsAligned()) {
614  x_RenderCurveSegment(pane, *it_1, positions, values, bottom_y, h, (int) amp);
615  }
616  }
617 
618  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
619  }
620 }
621 
622 
623 // Renders chromatogram corresponding to given segment of sequence.
624 // This function renders data as a curve for a single channel specified by "values".
626  const IAlnSegment& seg,
627  const CTraceData::TPositions& positions,
628  const CTraceData::TValues& values,
629  int bottom_y, int /*h*/, int amp)
630 {
631  IRender& gl = GetGl();
632 
633  const TModelRect rc_vis = pane.GetVisibleRect();
634 
635  const TSignedSeqRange& ch_range = seg.GetRange();
636  const TSignedSeqRange& ch_aln_range = seg.GetAlnRange();
637 
638  SChunkTranslator trans;
639  bool b_neg = m_Data->IsNegative();
640  trans.Init(ch_range, ch_aln_range, m_Data->IsNegative());
641 
642  // [from, to] - is sequence range for which graph is rendered
643  double from = max(m_Data->GetSeqFrom(), ch_range.GetFrom());
644  double to = min(m_Data->GetSeqTo(), ch_range.GetTo());
645 
646  double vis_from = trans.GetSeqPosFromAlnPos(rc_vis.Left());
647  double vis_to = trans.GetSeqPosFromAlnPos(rc_vis.Right());
648  if(vis_to < vis_from) {
650  swap(vis_from, vis_to);
651  }
652 
653  from = max(from, vis_from);
654  to = min(to, vis_to);
655 
656  if(from <= to) {
657  int sm_start = x_FindSampleToLeft(from);
658  int sm_end = x_FindSampleToRight(to + 1);
659  sm_start = max(0, sm_start);
660  sm_end = min(sm_end, m_Data->GetSamplesCount() - 1);
661 
662  if(sm_start <= sm_end) {
663  gl.Begin(GL_QUAD_STRIP);
664  TModelUnit offset_x = pane.GetOffsetX();
665 
666  // check if start interpolation is needed
667  CTraceData::TFloatSeqPos sm_start_seqpos = positions[sm_start];
668  if(sm_start_seqpos < from) {
669  if(sm_start + 1 < sm_end) {
670  double v1 = values[sm_start];
671  double v2 = values[sm_start + 1];
672  double x1 = sm_start_seqpos;
673  double x2 = positions[sm_start + 1];
674  double v = v1 + ((from - x1) * (v2 - v1) / (x2 - x1));
675  v *= amp;
676 
677  double aln_from = trans.GetAlnPosFromSeqPos(from + (b_neg ? -1 : 0));
678  gl.Vertex2d(aln_from - offset_x, bottom_y - v);
679  //gl.Vertex2d(aln_from - offset_x, bottom_y);
680  }
681  sm_start++;
682  }
683  // render regular samples
684  for( int i_sm = sm_start; i_sm < sm_end; i_sm++ ) {
685  TModelUnit seqpos = positions[i_sm];
686  double v = values[i_sm];
687  v *= amp;
688 
689  double aln_pos = trans.GetAlnPosFromSeqPos(seqpos + (b_neg ? -1 : 0));
690  gl.Vertex2d(aln_pos - offset_x, bottom_y - v);
691  //gl.Vertex2d(aln_pos - offset_x, bottom_y);
692  }
693  // render end point
694  if( sm_end - 1 > sm_start) { // interpolate end point
695  double v1 = values[sm_end -1];
696  double v2 = values[sm_end];
697  double x1 = positions[sm_end - 1];
698  double x2 = positions[sm_end];
699  double v = v1 + ((to + 1 - x1) * (v2 - v1) / (x2 - x1));
700  v *= amp;
701 
702  double aln_to = trans.GetAlnPosFromSeqPos(to + (b_neg ? 0 : 1));
703  gl.Vertex2d(aln_to - offset_x, bottom_y - v);
704  //gl.Vertex2d(aln_to - offset_x, bottom_y);
705  } else {
706  TModelUnit seqpos = positions[sm_end];
707  double v = values[sm_end];
708  v *= amp;
709 
710  double aln_pos = trans.GetAlnPosFromSeqPos(seqpos);
711  gl.Vertex2d(aln_pos - offset_x, bottom_y - v);
712  //gl.Vertex2d(aln_pos - offset_x, bottom_y);
713  }
714  gl.End();
715  }
716  }
717 }
718 
719 
720 /// Render signals for all channels as gradient-color bands with color intensity
721 /// proprotional to signal strength.
723  IAlnSegmentIterator& it_seg)
724 {
725  IRender& gl = GetGl();
726 
727  //_TRACE("\nx_RenderIntensityGraphs");
728  const CTraceData::TPositions& positions = m_Data->GetPositions();
729 
730  const TVPRect& rc_vp = pane.GetViewport();
731  const TModelRect rc_vis = pane.GetVisibleRect();
732 
733  // calculate layout
734  int av_h = h - 2 * kGraphOffsetY; // height available for intensity bands
735  int band_h = av_h / 4;
736  int off = (av_h - 4 * band_h) / 2; // rounding error compensation
737  int top_y = rc_vp.Bottom() - (y + kGraphOffsetY + off);
738 
739  TModelUnit left = rc_vis.Left();
740  TModelUnit scale_x = pane.GetScaleX();
741 
742  TVPUnit range_pix_start = rc_vp.Left();
743  TVPUnit range_pix_end = rc_vp.Right();
744 
745  SChunkTranslator trans;
746 
747  gl.Begin(GL_LINES);
748 
749  // iterate by pixels,samples and chunks
750  for( int pix = range_pix_start; pix <= range_pix_end && it_seg; ++it_seg) {
751  const IAlnSegment& seg = *it_seg;
752  if(seg.IsAligned()) {
753  // calculate samples range by segment
754  const TSignedSeqRange& ch_range = seg.GetRange();
755  const TSignedSeqRange& ch_aln_range = seg.GetAlnRange();
756  trans.Init(ch_range, ch_aln_range, m_Data->IsNegative());
757 
758  // [from, to] - is sequence range for which graph is rendered
759  double from = max(m_Data->GetSeqFrom(), ch_range.GetFrom());
760  double to = min(m_Data->GetSeqTo(), ch_range.GetTo());
761 
762  double vis_from = trans.GetSeqPosFromAlnPos(rc_vis.Left());
763  double vis_to = trans.GetSeqPosFromAlnPos(rc_vis.Right());
764  if(vis_to < vis_from) {
766  swap(vis_from, vis_to);
767  }
768 
769  from = max(from, vis_from);
770  to = min(to, vis_to);
771 
772  // [sm_start, sm_end] - samples range being rendered
773  int sm_start = x_FindSampleToLeft(from);
774  int sm_end = x_FindSampleToRight(to + 1);
775  sm_start = max(sm_start, 0);
776  sm_end = min(sm_end, m_Data->GetSamplesCount() - 1);
777 
778  // calculate pixels range to render
779  double aln_from = trans.GetAlnPosFromSeqPos(from);
780  double aln_to = trans.GetAlnPosFromSeqPos(to);
781  if(m_Data->IsNegative()) {
782  swap(aln_from, aln_to);
783  }
784  aln_to += 1;
785 
786  TVPUnit pix_start = range_pix_start + (TVPUnit) floor((aln_from - left) / scale_x);
787  TVPUnit pix_end = range_pix_start + (TVPUnit) ceil((aln_to - left) / scale_x);
788  pix_start = max(pix_start, range_pix_start);
789  pix_end = min(pix_end, range_pix_end);
790 
791  int sm_inc = m_Data->IsNegative() ? -1 : +1;
792 
793  int band_y = top_y;
794  for( int i_ch = 0; i_ch < 4; i_ch++ ) { // for every channel (i_ch - channel index)
795  int ch_index = (m_Props.m_bReverseColors &&
796  m_Data->IsNegative()) ? (i_ch ^ 2) : i_ch;
797  int ch = CTraceData::eA + ch_index;
798 
801 
802  double x1 = 0.0, x2 = 0.0, pix_x1 = 0.0, pix_x2 = 0.0;
803  double v1, v2, s, dx, sum, sum_pix_x;
804 
805  int sample = m_Data->IsNegative() ? sm_end : sm_start;
806  _ASSERT(sample >= 0);
807 
808  for( TVPUnit pix = pix_start; pix <= pix_end; pix++ ) { // for each pixel
809  // calculate average value for "pix" pixel by integrating values
810  // over the range [pix, pix+1]
811  sum = 0; // integral from values by pix_x
812  sum_pix_x = 0; // length of integrated range
813 
814  x1 = positions[sample];
815  if(m_Data->IsNegative())
816  x1 -= 1.0;
817  pix_x1 = range_pix_start + (trans.GetAlnPosFromSeqPos(x1) - left) / scale_x;
818  v1 = v2 = values[sample]; //#####
819 
820  if(pix_x1 < pix + 1) {
821 
822  bool b_next_point = m_Data->IsNegative() ? (sample > sm_start) : (sample < sm_end);
823  if(b_next_point) { // there is second point available
824  x2 = positions[sample + sm_inc];
825  if(m_Data->IsNegative())
826  x2 -= 1.0;
827  pix_x2 = range_pix_start + (trans.GetAlnPosFromSeqPos(x2) - left) / scale_x;
828  v2 = values[sample + sm_inc];
829 
830  if(pix_x1 < pix) { // fisrt sample is to the left of this pixel
831  // replace it fake interpolated sample at x = "pix"
832  v1 += (v2 - v1) * (pix - pix_x1) / (pix_x2 - pix_x1);
833  pix_x1 = pix;
834  }
835  }
836 
837  while(b_next_point && pix_x2 <= pix + 1) // while second point is inside pixel
838  {
839  dx = pix_x2 - pix_x1;
840  s = 0.5 * (v1 + v2) * dx;
841  _ASSERT(s >=0 && dx >= 0);
842 
843  sum += s;
844  sum_pix_x += dx;
845 
846  sample += sm_inc; // advance, x2 becomes x1
847  pix_x1 = pix_x2;
848  v1 = v2;
849 
850  b_next_point = m_Data->IsNegative() ? (sample > sm_start) : (sample < sm_end);
851  if(b_next_point) {
852  x2 = positions[sample + sm_inc];
853  if(m_Data->IsNegative())
854  x2 -= 1.0;
855  pix_x2 = range_pix_start + (trans.GetAlnPosFromSeqPos(x2) - left) / scale_x;
856  v2 = values[sample + sm_inc];
857  } else break;
858  }
859  _ASSERT(pix_x1 <= pix + 1);
860 
861  if(b_next_point && pix_x2 > pix + 1) { // second point is outside pixel
862  dx = pix + 1 - pix_x1;
863  _ASSERT(dx >= 0);
864 
865  double v = v1 + (v2 - v1) * dx / (pix_x2 - pix_x1);
866  s = 0.5 * (v1 + v) * dx;
867 
868  _ASSERT(s >=0 && dx >= 0);
869 
870  sum += s;
871  sum_pix_x += dx;
872  }
873  double av_v = (sum_pix_x) > 0 ? sum / sum_pix_x : 0;
874 
875  // render pixel
876  double norm = (MaxSignal == 0) ? 0 : (av_v / MaxSignal);
877  const CRgbaColor& col = GetColorByValue(norm, i_ch);
878  gl.ColorC(col);
879  gl.Vertex2d(pix, band_y);
880  gl.Vertex2d(pix, band_y - band_h - 1);
881  } // if(pix < pix + 1)
882  }
883  band_y -= band_h;
884  }
885  }
886  }
887  gl.End();
888 }
889 
890 // returns gradient color corresponding to normalized [0, 1.0] value "value"
891 // for channel specified by "signal"
892 const CRgbaColor& CTraceGraph::GetColorByValue(double value, int signal) const
893 {
894  _ASSERT(value >= 0 && value <= 1.0);
895  _ASSERT(signal >= 0 && signal <= 3);
896 
897  int i = (int) (value * kGradColors);
898  i = min(i, kGradColors);
899  int index = signal * kGradColors + i;
900  return m_vSignalColors[index];
901 }
902 
903 /// returns index of rightmost sample having m_SeqPos less then "pos".
904 /// if "pos" is to the left of the trace range function returns -1,
905 /// if "pos" is to the right of the trace range functions returns "n_samples"
906 int CTraceGraph::x_FindSampleToLeft(double pos) const
907 {
908  int n_samples = m_Data->GetSamplesCount();
909  if(pos < m_Data->GetSeqFrom() || n_samples == 0) {
910  return -1;
911  } else if(pos > m_Data->GetSeqTo()) {
912  return n_samples;
913  } else {
914  const CTraceData::TPositions& positions = m_Data->GetPositions();
915  double scale = ((double) n_samples) / m_Data->GetSeqLength();
916 
917  // calculate approximate sample index
918  int i = (int) (scale * (pos - m_Data->GetSeqFrom()));
919  i = min(i, n_samples - 1);
920  i = max(i, 0);
921 
922  if(positions[i] > pos) {
923  for( ; i > 0 && positions[i] > pos; i-- ) {
924  }
925  } else {
926  for( ; ++i < n_samples && positions[i] < pos; ) {
927  }
928  i--;
929  }
930  return i;
931  }
932 }
933 
934 
935 /// returns index of the leftmost sample having m_SeqPos greater than "pos"
936 /// if "pos" is to the left of the trace range function returns -1,
937 /// if "pos" is to the right of the trace range functions returns "n_samples"
938 int CTraceGraph::x_FindSampleToRight(double pos) const
939 {
940  int n_samples = m_Data->GetSamplesCount();
941  if(pos < m_Data->GetSeqFrom() || n_samples == 0) {
942  return -1;
943  } else if(pos > m_Data->GetSeqTo()) {
944  return n_samples;
945  } else {
946  const CTraceData::TPositions& positions = m_Data->GetPositions();
947  double scale = ((double) n_samples) / m_Data->GetSeqLength();
948 
949  // calculate approximate sample index
950  int i = (int) (scale * (pos - m_Data->GetSeqFrom()));
951  i = min(i, n_samples - 1);
952  i = max(i, 0);
953 
954  if(positions[i] > pos) {
955  for( ; i > 0 && positions[i] > pos; i-- ) {
956  }
957  i++;
958  } else {
959  for( ; ++i < n_samples && positions[i] < pos; ) {
960  }
961  }
962  return i;
963  }
964 }
965 
966 
CBioseq_Handle –.
CGlAttrGuard - guard class for restoring OpenGL attributes.
Definition: glutils.hpp:130
class CGlPane
Definition: glpane.hpp:62
TModelRect m_ModelRect
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
CTraceData * LoadData()
Definition: trace_data.cpp:85
TSignedSeqPos GetSeqFrom() const
Sequence related information.
Definition: trace_data.hpp:147
double TFloatSeqPos
Definition: trace_data.hpp:75
bool IsNegative() const
Definition: trace_data.hpp:159
TConfidence GetConfidence(TSignedSeqPos pos) const
Definition: trace_data.hpp:163
float TSignalValue
Definition: trace_data.hpp:76
TSignalValue GetMax(EChannel signal) const
Definition: trace_data.cpp:277
int GetSamplesCount() const
Definition: trace_data.hpp:174
TValues & GetValues(EChannel signal)
Definition: trace_data.cpp:243
TConfidence GetMaxConfidence() const
Definition: trace_data.cpp:272
TSignedSeqPos GetSeqTo() const
Definition: trace_data.hpp:151
TPositions & GetPositions()
Definition: trace_data.hpp:179
vector< TFloatSeqPos > TPositions
Definition: trace_data.hpp:78
void CalculateMax()
Definition: trace_data.cpp:255
vector< TSignalValue > TValues
Definition: trace_data.hpp:79
TSignedSeqPos GetSeqLength() const
Definition: trace_data.hpp:155
CTraceGraphProperties.
Definition: trace_graph.hpp:50
EGraphState m_ConfGraphState
Definition: trace_graph.hpp:66
ESingnalStyle m_SignalStyle
Definition: trace_graph.hpp:64
EGraphState m_SignalGraphState
Definition: trace_graph.hpp:67
CTraceGraphProperties & operator=(const CTraceGraphProperties &orig)
Definition: trace_graph.cpp:60
void x_RenderIntensityGraphs(CGlPane &pane, int y, int h, IAlnSegmentIterator &it)
Render signals for all channels as gradient-color bands with color intensity proprotional to signal s...
void x_RenderText(CGlPane &pane)
virtual bool Create()
void x_RenderSignalGraph(CGlPane &pane, int y, int h, IAlnSegmentIterator &it)
vector< CRgbaColor > m_vSignalColors
CTraceGraph(const objects::CBioseq_Handle &handle, bool b_neg_strand)
Definition: trace_graph.cpp:74
CTraceDataProxy m_DataProxy
int x_FindSampleToRight(double pos) const
returns index of the leftmost sample having m_SeqPos greater than "pos" if "pos" is to the left of th...
virtual void Render(CGlPane &pane)
void x_RenderContour(CGlPane &pane, int y, int conf_h, int total_h, IAlnSegmentIterator &it)
void SetSignalGraphState(EGraphState state)
virtual void Destroy()
virtual ~CTraceGraph()
Definition: trace_graph.cpp:84
void x_RenderCurveSegment(CGlPane &pane, const IAlnSegment &seg, const CTraceData::TPositions &positions, const CTraceData::TValues &values, int bottom_y, int h, int amp)
void SetConfGraphState(EGraphState state)
virtual bool IsCreated() const
Graph is not considered fully functional until it has been "created" by the call to create function.
CTraceData * m_Data
void x_RenderConfGraph(CGlPane &pane, int y, int h, IAlnSegmentIterator &it)
int x_GetConfGraphH() const
Definition: trace_graph.cpp:98
virtual bool NeedTooltip(CGlPane &pane, int vp_x, int vp_y)
const CRgbaColor & GetColorByValue(double value, int signal) const
CGlTextureFont m_Font
int x_GetSignalGraphH() const
CRgbaColor m_TextColor
virtual string GetTooltip()
virtual const IAlnRowGraphProperties * GetProperties() const
virtual void SetProperties(IAlnRowGraphProperties *props)
int x_FindSampleToLeft(double pos) const
returns index of rightmost sample having m_SeqPos less then "pos".
CTraceGraphProperties m_Props
virtual TVPPoint PreferredSize()
IAlnRowGraphProperties.
Alignment segment iterator interface.
virtual IAlnSegmentIterator * Clone(void) const =0
Create a copy of the iterator.
Alignment segment interface.
virtual const TSignedRange & GetRange(void) const =0
Get the selected row range.
bool IsAligned(void) const
virtual const TSignedRange & GetAlnRange(void) const =0
Get alignment range for the segment.
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
int TSignedSeqPos
Type for signed sequence position.
Definition: ncbimisc.hpp:887
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
#define NULL
Definition: ncbistd.hpp:225
#define _VERIFY(expr)
Definition: ncbidbg.hpp:161
const CVect2< U > & v2
Definition: globals.hpp:440
GLdouble TModelUnit
Definition: gltypes.hpp:48
virtual void Enable(GLenum glstate)=0
bool OpenOrtho()
Definition: glpane.hpp:427
virtual void Begin(GLenum mode)=0
Start rendering.
CGlPoint< TVPUnit > TVPPoint
Definition: gltypes.hpp:50
T Top() const
Definition: glrect.hpp:84
virtual void BlendFunc(GLenum sfactor, GLenum dfactor)=0
Options to be used when GL_BLEND is enabled.
T Bottom() const
Definition: glrect.hpp:82
bool OpenPixels()
Definition: glpane.hpp:432
void Color3d(GLdouble r, GLdouble g, GLdouble b)
Definition: irender.hpp:100
IRender & GetGl()
convenience function for getting current render manager
void Vertex2d(GLdouble x, GLdouble y)
Definition: irender.hpp:185
T Right() const
Definition: glrect.hpp:83
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
TModelUnit GetOffsetY() const
Definition: glpane.hpp:415
T Left() const
Definition: glrect.hpp:81
bool PtInRect(T x, T y) const
Definition: glrect.hpp:154
virtual void End()=0
Finish rendering (create buffer and send to renderer)
void Inflate(T d_x, T d_y)
Definition: glrect.hpp:178
void Close(void)
Definition: glpane.cpp:178
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
int TVPUnit
Definition: gltypes.hpp:47
EProjectionMode GetProjMode(void) const
Definition: glpane.hpp:437
virtual void TextOut(const char *text) const
TextOut interface Write the specified text and set up state and transformation as needed.
TModelRect & GetVisibleRect(void)
Definition: glpane.hpp:357
virtual void Disable(GLenum glstate)=0
glDisable()
virtual void LineWidth(GLfloat w)=0
Set line width for drawing: glLineWidth()
TModelUnit GetScaleX(void) const
Definition: glpane.cpp:118
TModelUnit GetOffsetX() const
Definition: glpane.hpp:410
virtual void ColorC(const CRgbaColor &c)=0
Set current color (glColor{3,4}{f,d}{v,})
void Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
Definition: irender.hpp:193
@ eAlign_Left
Definition: glfont.hpp:102
@ eOrtho
Definition: glpane.hpp:66
position_type GetLength(void) const
Definition: range.hpp:158
TThisType & IntersectWith(const TThisType &r)
Definition: range.hpp:317
bool NotEmpty(void) const
Definition: range.hpp:152
CRange< TSignedSeqPos > TSignedSeqRange
Definition: range.hpp:420
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
TTo GetTo(void) const
Get the To member data.
Definition: Range_.hpp:269
TFrom GetFrom(void) const
Get the From member data.
Definition: Range_.hpp:222
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
where boath are integers</td > n< td ></td > n</tr > n< tr > n< td > tse</td > n< td > optional</td > n< td > String</td > n< td class=\"description\"> TSE option controls what blob is orig
int i
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
T max(T x_, T y_)
T min(T x_, T y_)
T negative(T x_)
const TSignedSeqRange * m_AlnRange
double GetSeqPosFromAlnPos(double aln_pos)
double GetAlnPosFromSeqPos(double seq_pos)
const TSignedSeqRange * m_SeqRange
void Init(const TSignedSeqRange &seq_range, const TSignedSeqRange &aln_range, bool negative)
TSignedSeqPos GetAlnPosFromSeqPos(TSignedSeqPos seq_pos)
TSignedSeqPos GetSeqPosFromAlnPos(TSignedSeqPos aln_pos)
#define _ASSERT
USING_SCOPE(objects)
static const int kSignalGraphPrefH
Definition: trace_graph.cpp:94
static const int kGradColors
CTraceGraph.
Definition: trace_graph.cpp:72
static const float kEps
static const int kGraphOffsetY
Definition: trace_graph.cpp:91
static const int kTextOff
static const int kIntBandSpace
static const int kCollapsedGraphH
Definition: trace_graph.cpp:95
static const int kConfGraphPrefH
Definition: trace_graph.cpp:93
Modified on Fri Sep 20 14:57:38 2024 by modify_doxy.py rev. 669887