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

Go to the SVN repository for this file.

1 /* $Id: alignment_glyph.cpp 47479 2023-05-02 13:24:02Z ucko $
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: Vlad Lebedev, Liangshou Wu
27  *
28  * File Description:
29  * CAlignGlyph -- utility class to layout alignments
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistd.hpp>
34 #include <objmgr/util/sequence.hpp>
36 #include <objects/seq/MolInfo.hpp>
42 
48 #include <gui/objutils/tooltip.hpp>
49 #include <gui/objutils/utils.hpp>
50 
51 #include <gui/opengl/irender.hpp>
52 #include <gui/opengl/glutils.hpp>
56 
58 
60 #include <math.h>
61 
64 
65 // How closely pack align. sequence when showing DNA alignments for proteins
66 // (pack 3 alignment bases into 1 sequence base)
67 static const TModelUnit kPWAlignPackLevel = 0.333;
68 static const TSeqPos kTailGlyphLen = 12;
69 static const TSeqPos kCompactTailGlyphLen = 2;
70 
71 static const int kAlignRowSpace = 3;
72 static const int kLabelSpace_v = 2;
73 
74 static const int kLabelSpace_h = 5;
75 static const int kCompactLabelSpace_h = 1;
76 
78  const CSeq_align_Handle& orig_align,
79  const CSeq_align& mapped_align,
80  int orig_anchor)
81  : m_AlnMgr(aln_mgr)
82  , m_SeqAlign(&mapped_align)
83  , m_OrigSeqAlign(orig_align)
84  , m_OrigAnchor(orig_anchor)
85  , m_ShowScore(false)
86  , m_DisableTooltipsCaching(false)
87  , m_FadeFactor(1.0f)
88 {
90  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
91 
92  TSignedSeqPos start = m_AlnMgr->GetSeqStart(anchor) / base_width_anchor;
93  TSignedSeqPos stop = m_AlnMgr->GetSeqStop (anchor) / base_width_anchor;
94 
95  m_Location.Reset(new CSeq_loc());
96  m_Location->SetInt().SetFrom(start);
97  m_Location->SetInt().SetTo (stop);
98  if (x_IsPWAlign()) {
100  m_Location->SetStrand(eNa_strand_plus);
101  } else {
102  m_Location->SetStrand(eNa_strand_minus);
103  }
104  }
105 
106  CConstRef<CSeq_id> id(&m_AlnMgr->GetSeqId(anchor));
107  m_Location->SetId(*id);
108 }
109 
110 
111 bool CAlignGlyph::NeedTooltip(const TModelPoint& /*p*/, ITooltipFormatter& /*tt*/, string& /*t_title*/) const
112 {
113  return true;
114 }
115 
116 
117 void CAlignGlyph::GetTooltip(const TModelPoint& p, ITooltipFormatter& tt, string& t_title) const
118 {
119  if (!GetVisible())
120  return;
121  CScope& scope = m_Context->GetScope();
122  SConstScopedObject scoped_obj(&GetAlignment(), &scope);
123  CIRef<IGuiObjectInfo> gui_info(
124  CreateObjectInterface<IGuiObjectInfo>(scoped_obj, NULL));
125 
126  if ( !gui_info ) return;
127 
128  CGuiObjectInfoSeq_align* gui_info_aln =
129  dynamic_cast<CGuiObjectInfoSeq_align*>(gui_info.GetPointer());
130  if (gui_info_aln) {
131  gui_info_aln->SetAnchorRow(m_OrigAnchor);
132  gui_info_aln->SetFlippedStrands(m_Context->IsFlippedStrand());
133  gui_info_aln->SetScale(m_Context->GetScale());
134  gui_info_aln->SetDataSource(m_AlnMgr);
135  }
136 
137  TSeqPos at_p = (TSeqPos)-1;
138  if (p.X() >= 0) {
139  at_p = (TSeqPos)p.X();
140  }
141 
142  gui_info->GetToolTip(tt, t_title, at_p);
143  gui_info->GetLinks(tt, false);
144 
145  if (IsLastRow()) {
146  tt.AddRow("");
147  tt.AddRow("Last displayed alignment");
148  tt.AddRow("Alignment rows truncated for 'Adaptive' display");
149  tt.AddRow("To see all alignments select 'Show All'");
150  }
151 }
152 
153 
155 {
156  if (!GetVisible())
157  return;
158  CHTMLActiveArea area;
160  if (m_AlnMgr->GetNumRows() == 2) {
161  area.m_PositiveStrand =
163  }
164  area.m_Signature = GetSignature();
167  p_areas->push_back(area);
168 }
169 
170 
172 {
173  if (m_Intervals.size() == 1) {
174  return m_Intervals.front();
175  }
176 
177  return m_Location->GetTotalRange();
178 }
179 
180 
182 {
183  return true;
184 }
185 
186 
188 {
189  return CConstRef<CObject>(m_OrigSeqAlign.GetSeq_align());
190 }
191 
192 
193 void CAlignGlyph::GetObjects(vector<CConstRef<CObject> >& objs) const
194 {
195  objs.emplace_back(m_OrigSeqAlign.GetSeq_align());
196 }
197 
198 
200 {
201  return m_OrigSeqAlign.GetSeq_align() == obj.GetPointer();
202 }
203 
204 
205 const objects::CSeq_loc& CAlignGlyph::GetLocation(void) const
206 {
207  return *m_Location;
208 }
209 
210 
212 {
213  if (x_IsSRA()) {
214  int aligned_seq = m_AlnMgr->GetAnchor() == 0 ? 1 : 0;
215  CSeq_loc csra_loc;
216  csra_loc.Assign(*m_Location);
217  csra_loc.SetId(m_AlnMgr->GetSeqId(aligned_seq));
219  GetOrigAlignment().GetSeq_align().GetObject(),
220  csra_loc, &m_Context->GetScope(), m_OrigSeqAlign.GetAnnot());
221  }
222  else {
224  GetOrigAlignment().GetSeq_align().GetObject(),
225  GetLocation(), &m_Context->GetScope(), m_OrigSeqAlign.GetAnnot());
226  }
227 }
228 
229 
231 {
232  return m_Intervals;
233 }
234 
235 
236 inline double CompressLength(double len)
237 {
238  if(len <= 10.0) {
239  return len;
240  } else {
241  double log = log10(len) * 10;
242  return log;
243  }
244 }
245 
246 
248 {
249  if (ctx.seq_range.Empty())
250  return;
251 
252  IRender& gl = GetGl();
253  int anchor = m_AlnMgr->GetAnchor();
254  int row_num = m_AlnMgr->GetNumRows();
255 
256  // color the gap differently
257  //CGlAttrGuard AttrGuard(GL_LINE_BIT);
258  gl.Disable(GL_LINE_SMOOTH);
259 
260  const TModelUnit y_center = ctx.yy + ctx.half;
261  CRgbaColor gap_color_min(0.78f, 0.5f, 0.5f, m_FadeFactor);
262  CRgbaColor gap_color_max(0.6f, 0.0f, 0.0f, m_FadeFactor);
263 
264  for (int row = 0; row < row_num; ++row) {
265  if (row == anchor) {
266  continue; // skip master seq
267  }
268  unique_ptr<IAlnSegmentIterator> p_it(
271 
272  for (IAlnSegmentIterator& it = *p_it; it; ++it) {
273  const IAlnSegment& seg = *it;
274  if ( !(seg.GetType() & IAlnSegment::fIndel) ||
275  !seg.GetRange().Empty() ) {
276  continue;
277  }
278 
279  const IAlnSegment::TSignedRange& curr_aln_r = seg.GetAlnRange();
280  TModelUnit curr_seq_from =
281  m_AlnMgr->GetSeqPosFromAlnPos(anchor, curr_aln_r.GetFrom()) /
282  ctx.base_width_anchor;
283  TModelUnit curr_seq_to =
284  m_AlnMgr->GetSeqPosFromAlnPos(anchor, curr_aln_r.GetTo()) /
285  ctx.base_width_anchor;
286  if (curr_seq_from > curr_seq_to) {
287  swap (curr_seq_from, curr_seq_to);
288  }
289  curr_seq_to += 1.0 / ctx.base_width_anchor;
290  TModelUnit gap_size = m_Context->SeqToScreen(curr_seq_to - curr_seq_from);
291  if (gap_size > 1.5) {
292  gl.LineWidth(2.0);
294  const IAlnGraphicDataSource::TCigarPair *cigar = m_AlnMgr->GetCigarAtAlnPos(row, curr_aln_r.GetFrom());
295  if ((nullptr != cigar) && (IAlnGraphicDataSource::eCigar_N == (*cigar).first)) {
297  }
298  m_Context->DrawLine(curr_seq_from, y_center, curr_seq_to, y_center);
299  } else {
300  /*
301  if (gap_size > 1.0) {
302  gap_size = 1.0;
303  } else if (gap_size < 0.1) {
304  gap_size = 0.1;
305  }
306  if (gap_size > 1.0) {
307  CRgbaColor gap_color_ins(CRgbaColor::Interpolate(gap_color_max,
308  gap_color_min, gap_size));
309  gl.ColorC(gap_color_ins);
310  gl.LineWidth(1.0);
311  TModelUnit c_x = (curr_seq_from + curr_seq_to) * 0.5;
312  m_Context->DrawLine_NoAA(c_x, ctx.yy, c_x, ctx.yy + ctx.bar_h);
313  }
314  */
315  }
316  }
317  }
318  gl.LineWidth(1.0f);
319 }
320 
322 {
323  if (ctx.seq_range.Empty())
324  return;
325 
326  IRender& gl = GetGl();
327  TModelUnit over = 2.0;
328  TModelUnit down = 3.0;
329  const TModelUnit y1 = ctx.yy + down;
330  const TModelUnit y2 = ctx.yy + ctx.bar_h - down;
331 
333  CRgbaColor color_min = color_max;
334  color_min.Lighten(0.6f);
335  int anchor = m_AlnMgr->GetAnchor();
336  int row_num = m_AlnMgr->GetNumRows();
337  CGlAttrGuard AttrGuard(GL_LINE_BIT);
338  gl.Disable(GL_LINE_SMOOTH);
339 
340  for (int row = 0; row < row_num; ++row) {
341  if (row == anchor) {
342  continue; // skip master seq
343  }
344  unique_ptr<IAlnSegmentIterator> p_it(
347 
348  int last_aligned_seg_to_anchor = -2;
349  int last_aligned_seg_to_curr = -2;
350  int last_aligned_seg_from_anchor = -2;
351  int last_aligned_seg_from_curr = -2;
352 
353  int last_large_ins = -100000; // >= 5 bases
354 
355  int seg_iter_dir = 0; // 0: unknown, 1: forward (anchor), -1: reverse (anchor)
356  for (IAlnSegmentIterator& it = *p_it; it; ++it) {
357  const IAlnSegment& seg = *it;
358  TSeqPos start = 0;
359  int ins_len = 0;
360  if ( !(seg.GetType() & IAlnSegment::fIndel) ||
361  seg.GetRange().Empty() ) {
362  // it is not marked as insertion
363  // check if it is intron
364  if (seg.GetType() & IAlnSegment::fAligned) {
365  if (seg_iter_dir == 0) {
366  int anchor_to =
368  int anchor_from =
370  if (last_aligned_seg_to_anchor < 0) {
371  // It must be the first segment (unknow iterator direction)
372  last_aligned_seg_to_anchor = anchor_to;
373  last_aligned_seg_from_anchor = anchor_from;
374  last_aligned_seg_to_curr = seg.GetRange().GetTo();
375  last_aligned_seg_from_curr = seg.GetRange().GetFrom();
376  } else {
377  if (anchor_to < last_aligned_seg_to_anchor || anchor_from < last_aligned_seg_to_anchor) {
378  seg_iter_dir = -1;
379  } else {
380  seg_iter_dir = 1;
381  }
382  }
383  }
384 
385  if (seg_iter_dir == -1) {
386  TSeqPos t_pos = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
388  if ((int)t_pos == last_aligned_seg_from_anchor - 1) {
389  start = t_pos / ctx.base_width_anchor;
390  if (ctx.reverse_strand) {
391  ins_len = seg.GetRange().GetFrom() - last_aligned_seg_to_curr;
392  } else {
393  ins_len = last_aligned_seg_from_curr - seg.GetRange().GetTo();
394  }
395  ins_len -= 1;
396  }
397  last_aligned_seg_to_anchor = t_pos;
398  last_aligned_seg_from_anchor = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
400  } else if (seg_iter_dir == 1) {
401  TSeqPos f_pos = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
403  if ((int)f_pos == last_aligned_seg_to_anchor + 1) {
404  start = f_pos / ctx.base_width_anchor;
405  if (ctx.reverse_strand) {
406  ins_len = last_aligned_seg_from_curr - seg.GetRange().GetTo();
407  } else {
408  ins_len = seg.GetRange().GetFrom() - last_aligned_seg_to_curr;
409  }
410  ins_len -= 1;
411  }
412  last_aligned_seg_from_anchor = f_pos;
413  last_aligned_seg_to_anchor = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
415  }
416  last_aligned_seg_from_curr = seg.GetRange().GetFrom();
417  last_aligned_seg_to_curr = seg.GetRange().GetTo();
418  }
419  } else {
420  // The left/right/backward/forward flag works very strangely.
421  // We need to hack it by looking at the strand flag.
422  start = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
423  seg.GetAlnRange().GetFrom(),
425 
426  start /= ctx.base_width_anchor;
427  ins_len = seg.GetRange().GetLength();
428  // reset to avoid drawing insertion twice
429  last_aligned_seg_to_anchor = -2;
430  last_aligned_seg_from_anchor = -2;
431  }
432  if (ins_len <= 0) continue;
433 
435 
436  TModelUnit ins_len_pix = m_Context->SeqToScreen(ins_len);
437  // adjust it to the anchor sequence base length
438  ins_len_pix /= ctx.base_width_anchor;
439 
440  if (ins_len < 5) {
441  if (((int)start - last_large_ins) < m_Context->ScreenToSeq(1.0)) {
442  // skip the minor ones that overlap with the last major one
443  continue;
444  }
445  } else if (ins_len_pix > 2.0) {
446  // store the last major insert ( > 5 bases) location
447  last_large_ins = (int)start;
448  }
449  if (ins_len_pix < 0.1f)
450  continue;
451 
452  if (ins_len_pix > 1.5 && m_Config->m_CompactMode == CAlignmentConfig::eNormal) {
453  TModelUnit scale = min(10.0 * ins_len/ m_Context->GetScale(), 1.0);
454  CRgbaColor color_ins(CRgbaColor::Interpolate(color_max, color_min, scale));
455  gl.ColorC(color_ins);
456  m_Context->DrawLine(start, ctx.yy, start, ctx.yy + ctx.bar_h);
457  TModelUnit size_in_model
458  = min(m_Context->ScreenToSeq(4), (TModelUnit)ins_len);
459  m_Context->DrawTriangle(start, y1,
460  start + size_in_model, ctx.yy - over,
461  start - size_in_model, ctx.yy - over);
462  m_Context->DrawTriangle(start, y2,
463  start - size_in_model, ctx.yy + ctx.bar_h + over,
464  start + size_in_model, ctx.yy + ctx.bar_h + over);
465  TModelUnit len = max(CompressLength(ins_len), size_in_model * 2.0);
466  TModelUnit x1 = start - len * 0.5;
467  TModelUnit x2 = x1 + len;
468  m_Context->DrawLine(x1, ctx.yy - over, x2, ctx.yy - over);
469  m_Context->DrawLine(x1, ctx.yy + ctx.bar_h + over, x2, ctx.yy + ctx.bar_h + over);
470  }
471  }
472  }
473 }
474 
476 {
477 
478  TMUnitRanges unaligned_regions;
479  x_DrawInternalUnalignedRegions(ctx, unaligned_regions);
480  sort(unaligned_regions.begin(), unaligned_regions.end(),
481  [](TModelRange const& a, TModelRange const& b) -> bool
482  {
483  return a.GetFrom() < b.GetFrom();
484  });
485  TModelUnit y = ctx.yy + ctx.half;
486  double barh = abs(m_Context->GetGlPane()->GetScaleY() * ctx.bar_h);
487  // if bar height i sless than 2pix
488  // set y to top so that the following alignment bar covers it
489  // (blue band issue)
490  if (barh < 2.)
491  y = ctx.yy;
492  if (unaligned_regions.empty()) {
493  m_Context->DrawLine_NoAA(from, y, to, y);
494  } else {
495  TModelUnit ln_start = from;
496  for (const auto& unaligned_rng : unaligned_regions) {
497  m_Context->DrawLine_NoAA(ln_start, y, unaligned_rng.GetFrom() - 1, y);
498  ln_start = unaligned_rng.GetToOpen();
499  }
500  m_Context->DrawLine_NoAA(ln_start, y, to, y);
501  }
502 }
503 
505 {
506  if (ctx.seq_range.Empty())
507  return;
508 
509  TModelUnit seg_width(m_Context->GetGlPane()->GetViewport().Width());
510  if (m_Context->GetViewWidth() && (m_Context->GetViewWidth() != seg_width))
511  seg_width /= 5.0;
512  seg_width = m_Context->ScreenToSeq(seg_width);
513 
514  IRender& gl = GetGl();
515  // Don't draw the labels, if they are taller than the bar
516  const CGlTextureFont& l_font = m_Config->m_LabelFont;
517  TModelUnit h_text = gl.TextHeight(&l_font);
518 
519  int anchor = m_AlnMgr->GetAnchor();
520  int row_num = m_AlnMgr->GetNumRows();
521 
523 
524  TSignedSeqRange aln_range = ctx.aln_range;
525  if (aln_range.GetFrom() > 0) {
526  aln_range.SetFrom(aln_range.GetFrom() - 1);
527  }
528 
529  for (int row = 0; row < row_num; ++row) {
530  if (row == anchor) {
531  continue; // skip master seq
532  }
533 
534  unique_ptr<IAlnSegmentIterator> p_it(
537 
538  for (IAlnSegmentIterator& it = *p_it; it; ++it) {
539  const IAlnSegment& seg = *it;
540 
541  if (!(seg.GetType() & IAlnSegment::fUnaligned)) {
542  continue;
543  }
544  if (seg.GetRange().GetLength() <= 0)
545  continue;
546 
547  const IAlnSegment::TSignedRange& curr_aln_r = seg.GetAlnRange();
548 
549  TSignedSeqPos curr_seq_from =
550  m_AlnMgr->GetSeqPosFromAlnPos(anchor, curr_aln_r.GetFrom(), IAlnExplorer::eLeft) /
551  ctx.base_width_anchor;
552  TSignedSeqPos curr_seq_to =
553  m_AlnMgr->GetSeqPosFromAlnPos(anchor, curr_aln_r.GetTo(), IAlnExplorer::eRight) /
554  ctx.base_width_anchor;
555  if (curr_seq_from > curr_seq_to) {
556  swap(curr_seq_from, curr_seq_to);
557  }
558  TSeqRange curr_seq(curr_seq_from, curr_seq_to - 1);
559  if (curr_seq.GetLength() <= 1)
560  continue;
561 
562  TModelRange inrc = m_Context->IntersectVisible(curr_seq);
563  TSeqRange visible_range((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetTo());
564  if (visible_range.Empty())
565  continue;
566 
567  unaligned_regions.emplace_back(visible_range.GetFrom() + 1, visible_range.GetTo() + 1);
569 
570  TModelUnit y = ctx.yy + ctx.half;
571 
572  if (h_text > ctx.bar_h) {
573  m_Context->DrawStippledLine(visible_range.GetFrom() + 1, y, visible_range.GetTo() + 1, y);
574  continue;
575  }
576 
577  // label text that will be shown
578  string sLabelTextOut = NStr::IntToString(seg.GetRange().GetLength(), NStr::fWithCommas);
579  sLabelTextOut += " bp unaligned";
580 
581  TModelUnit label_width = m_Context->ScreenToSeq(gl.TextWidth(&l_font, sLabelTextOut.c_str()));
582  TModelUnit half_label = label_width / 2.0;
583 
584  int labelsCount = round(visible_range.GetLength() / seg_width);
585  if (!labelsCount) {
586  if ((label_width + label_width*0.5) >= visible_range.GetLength()) {
587  m_Context->DrawStippledLine(visible_range.GetFrom() + 1, y, visible_range.GetTo() + 1, y);
588  continue;
589  }
590  labelsCount = 1;
591  }
592 
593  TModelUnit yM = ctx.yy + ctx.bar_h - (ctx.bar_h - h_text) / 2;
594 
595 
596  TModelUnit part_size = visible_range.GetLength() / labelsCount;
597  TModelUnit xM;
598  TModelUnit xLF, xLT;
599  xLF = visible_range.GetFrom();
600  for (int i = 0; i < labelsCount; ++i) {
601  xM = visible_range.GetFrom() + part_size / 2.0 + i*part_size;
602  xLT = visible_range.GetFrom() + part_size / 2.0 + i*part_size - half_label;
603  m_Context->DrawStippledLine(xLF, y, xLT, y);
604  m_Context->TextOut(&l_font, sLabelTextOut.c_str(), xM, yM, true, true);
605  xLF = visible_range.GetFrom() + part_size / 2.0 + i*part_size + half_label;
606  }
607  m_Context->DrawStippledLine(xLF, y, visible_range.GetToOpen(), y);
608  }
609  }
610 }
611 
612 
613 
614 void CAlignGlyph::x_DrawTailGlyphs(const SDrawContext& ctx, bool show_label, const CRgbaColor& c_fg) const
615 {
616  IRender& gl = GetGl();
617  if (ctx.bar_h <= 2)
618  show_label = false;
619 
620  int aligned_seq = m_AlnMgr->GetAnchor() == 0 ? 1 : 0;
623  TModelUnit y_base = ctx.yy;
624 
625  TSignedSeqPos tail_5(0);
626  TSignedSeqPos tail_3(0);
627  TSignedSeqPos from(ctx.f);
628  TSignedSeqPos to(ctx.t);
629  m_AlnMgr->GetUnalignedTails(tail_5, tail_3, false);
630 
634  if (tail_5 > ctx.tail_5)
635  tail_5 -= ctx.tail_5;
636  else
637  tail_5 = 0;
638  if (tail_3 > ctx.tail_3)
639  tail_3 -= ctx.tail_3;
640  else
641  tail_3 = 0;
642  }
643 
644  // starting tail
645  if (tail_5 > 0) {
646  TModelUnit x_base = from - gap;
647  gl.ColorC(c_fg);
649  bool is_polya = CGuiObjectInfoSeq_align::IsPolyA(m_AlnMgr->GetBioseqHandle(aligned_seq), tail_5_rng.GetFrom(), tail_5_rng.GetToOpen());
650  m_Context->DrawUnalignedTail(x_base - size, x_base, y_base,
651  y_base + ctx.bar_h, is_polya, CRgbaColor(m_Config->m_TailColor, m_FadeFactor));
652  if (show_label) {
653  const CGlTextureFont& l_font = m_Config->m_LabelFont;
654  string len_str = NStr::IntToString(tail_5, NStr::fWithCommas);
655  TModelUnit num_len = gl.TextWidth(&l_font, len_str.c_str());
656 
657  TModelUnit xM = x_base - size - gap - m_Context->ScreenToSeq(num_len);
658  TModelUnit yM = y_base + ctx.bar_h - 2.0;
659 
660  TModelUnit h_text = gl.TextHeight(&l_font);
661 
662  if (h_text < ctx.bar_h) {
664  m_Context->TextOut(&l_font, len_str.c_str(), xM, yM, false);
665  }
666  }
667  }
668 
669  // ending tail
670  if (tail_3 > 0) {
671  TModelUnit x_base = to + gap + 1;
672  gl.ColorC(c_fg);
674  bool is_polya = CGuiObjectInfoSeq_align::IsPolyA(m_AlnMgr->GetBioseqHandle(aligned_seq), tail_3_rng.GetFrom(), tail_3_rng.GetToOpen());
675  m_Context->DrawUnalignedTail(x_base, x_base + size, y_base,
676  y_base + ctx.bar_h, is_polya, CRgbaColor(m_Config->m_TailColor, m_FadeFactor));
677  if (show_label) {
678  const CGlTextureFont& l_font = m_Config->m_LabelFont;
679  string len_str = NStr::IntToString(tail_3, NStr::fWithCommas);
680 
681  TModelUnit xM = x_base + size + gap;
682  TModelUnit yM = y_base + ctx.bar_h - 2.0;;
683 
684  TModelUnit h_text = gl.TextHeight(&l_font);
685 
686  if (h_text < ctx.bar_h) {
688  m_Context->TextOut(&l_font, len_str.c_str(), xM, yM, false);
689  }
690  }
691  }
692 }
693 
695 {
696  if (ctx.tail_5 > 0) {
698  }
699  if (ctx.tail_3 > 0) {
701  }
702  TSignedSeqPos tail_5 = 0;
703  TSignedSeqPos tail_3 = 0;
704  m_AlnMgr->GetUnalignedTails(tail_5, tail_3, false);
705  if ((tail_5 > ctx.tail_5) || (tail_3 > ctx.tail_3))
706  x_DrawTailGlyphs(ctx, true, c_fg);
707 }
708 
709 void CAlignGlyph::x_DrawUnalignedBar(const ETail tail, const SDrawContext& ctx, const CRgbaColor& c_fg) const
710 {
711  IRender& gl = GetGl();
712 
714 
715  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
716 
717  gl.PushMatrix();
718  gl.Scalef(m_Context->GetScale(), 1.0f, 1.0f);
719 
721  TSeqRange visible_range((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetTo());
722  if (!visible_range.Empty()) {
723  gl.Color4d(c_fg.GetRed(), c_fg.GetGreen(), c_fg.GetBlue(), m_FadeFactor);
724  TVPUnit start = m_Context->SeqToScreenX(visible_range.GetFrom());
725  TVPUnit stop = m_Context->SeqToScreenX(visible_range.GetToOpen());
726  gl.Rectd(start, ctx.yy, stop, ctx.yy + ctx.bar_h);
727  }
728 
729  gl.PopMatrix();
730 }
731 
732 void CAlignGlyph::x_DrawUnalignedRowSequence(const ETail tail, const SDrawContext& ctx, const CRgbaColor& c_fg) const
733 {
734  IRender& gl = GetGl();
735 
736  int anchor = m_AlnMgr->GetAnchor();
737  int aligned_seq = anchor == 0 ? 1 : 0;
738 
740 
741  TSeqRange visible_unaligned_range(range);
742  TModelRange inrc = m_Context->IntersectVisible(visible_unaligned_range);
743 
744  if (inrc.Empty()) {
745  return;
746  }
747 
748  visible_unaligned_range.SetFrom((TSeqPos)inrc.GetFrom());
749  visible_unaligned_range.SetTo((TSeqPos)inrc.GetTo());
750 
751  TSeqRange visible_sequence_range(x_ConvertAlnTaillRngToSeqRng(tail, ctx, visible_unaligned_range));
752 
753  gl.ColorC(c_fg);
754 
755  const CBioseq_Handle& mhndl = m_AlnMgr->GetBioseqHandle(anchor);
756  const CBioseq_Handle& hndl = m_AlnMgr->GetBioseqHandle(aligned_seq);
757  if (!hndl || !mhndl)
758  return;
759 
760  bool ab = mhndl.IsAa();
761  bool rb = hndl.IsAa();
762 
763  EAlignSpacing spacing(eOne2One);
764  if (!ab && rb) spacing = eOne2Three;
765  if (ab && !rb) spacing = eThree2One;
766 
767  try {
768 
770 
771  string seq, tmp_seq;
772  s_vec.GetSeqData(visible_sequence_range.GetFrom(), visible_sequence_range.GetTo(), tmp_seq);
773 
774  if (ctx.reverse_strand) {
775  if (rb) {
776  // protein sequence, just reverse it
777  CSeqManip::Reverse(tmp_seq, CSeqUtil::e_Iupacaa, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
778  }
779  else {
780  // nucleotide sequence, get reverse and complement
781  if (m_Context->IsFlippedStrand()) {
782  CSeqManip::Reverse(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
783  }
784  else {
785  CSeqManip::ReverseComplement(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
786  }
787  }
788  }
789  else {
790  if (!rb && m_Context->IsFlippedStrand()) {
791  CSeqManip::Complement(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
792  }
793  else {
794  swap(seq, tmp_seq);
795  }
796  }
797 
798  string translated_seq;
799  switch (spacing) {
800  case eOne2Three:
801  translated_seq = seq;
802  break;
803  case eThree2One: {
804  CGenetic_code gcode;
805  gcode.SetId(m_AlnMgr->GetGenCode(aligned_seq));
806  CSeqTranslator::Translate(seq, translated_seq, CSeqTranslator::fDefault, &gcode);
807  break;
808  }
809  default:
810  break;
811  }
812 
813  char bases[2];
814  bases[1] = '\0';
815  TVPUnit font_w = (TVPUnit)(gl.TextWidth(&(m_Config->m_SeqFont), "G") * 0.5f);
816  TModelUnit addon = 0.5 - m_Context->ScreenToSeq(font_w);
817 
818  TSeqPos sStart = visible_unaligned_range.GetFrom();
819 
821  // Draw characters (actg)
822  for (TSeqPos bp = 0; bp < seq.size(); bp++) {
823  TModelUnit pos = 0;
824  switch (spacing) {
825  case eOne2One:
826  pos = sStart + bp + addon;
827  break;
828  case eOne2Three:
829  pos = sStart + bp * 3 + addon + 1;
830  break;
831  case eThree2One:
832  pos = sStart + bp * kPWAlignPackLevel + addon - kPWAlignPackLevel;
833  break;
834  default:
835  break;
836  }
837 
838 
839  bases[0] = seq[bp];
840 
841  m_Context->TextOut(&m_Config->m_SeqFont, bases, pos, ctx.center_y + fs * 0.5, false);
842  } // for TSeqPos
843  }
844  catch (CException&) {
845  /// ignore exceptions - these are all objmgr related
846  }
847 }
848 
850 {
851  if (ctx.seq_range.Empty())
852  return;
853 
854  if (!(m_SeqAlign->GetSegs().Which() == CSeq_align::TSegs::e_Spliced && m_OrigAnchor == 1))
855  return;
856  IRender& gl = GetGl();
857  const CSpliced_seg& spliced_seg = m_SeqAlign->GetSegs().GetSpliced();
858  string splice5;
859  TSeqPos pre_stop = 0;
860  bool neg_genomic = (spliced_seg.GetSeqStrand(1) == eNa_strand_minus);
861  ITERATE (CSpliced_seg::TExons, exon_it, spliced_seg.GetExons()) {
862  const CSpliced_exon& exon = **exon_it;
863  string splice3;
864  if (exon.IsSetAcceptor_before_exon()) {
865  splice3 = exon.GetAcceptor_before_exon().GetBases();
866  }
867 
868  // render a bold red bar for non-consensus splice site
869  if ( !splice5.empty() && !splice3.empty() &&
870  !IsConsensusSplice(splice5, splice3) ) {
871  gl.LineWidth(4.0f);
873  m_Context->DrawLine(pre_stop, ctx.center_y,
874  neg_genomic ? exon.GetGenomic_end() + 1 :
875  exon.GetGenomic_start(), ctx.center_y);
876  gl.LineWidth(1.0f);
877  }
878  if (exon.IsSetDonor_after_exon()) {
879  splice5 = exon.GetDonor_after_exon().GetBases();
880  } else {
881  splice5 = kEmptyStr;
882  }
883  pre_stop = neg_genomic ?
884  exon.GetGenomic_start() : exon.GetGenomic_end() + 1;
885  }
886 }
887 
889 {
890  if (ctx.seq_range.Empty())
891  return;
892  CRgbaColor c;
893  if (ctx.override_color)
894  c = ctx.read_status_color;
895  else
896  c = c_fg;
897 
898  // Don't use blending here - just overwrite but take any alpha into account
899  if (m_FadeFactor < 1.0) {
900  c.Lighten(1.0f - m_FadeFactor);
901  }
902 
903  // m_Intervals - are calculated in UpdateBoundingBox
904  ITERATE(vector<TSeqRange>, it, m_Intervals) {
905  if (ctx.override_color)
906  m_Context->Draw3DQuad(it->GetFrom(), ctx.yy, it->GetTo(), ctx.yy + ctx.bar_h, c, true);
907  else
908  m_Context->Draw3DQuad(it->GetFrom(), ctx.yy, it->GetTo(), ctx.yy + ctx.bar_h, c, true);
909  }
910 }
911 
913 {
914  IRender& gl = GetGl();
915  // draw strand indicators
917  m_Context->SeqToScreen(ctx.whole_range.GetLength()) > 8.0) {
918  TModelUnit xM = (ctx.whole_range.GetFrom() + ctx.whole_range.GetTo()) * 0.5;
919  if (m_Context->WillSeqLetterFit()) {
920  // make sure we don't step on the sequence letter
921  // when sequence is shown
922  xM = ceil(xM);
923  }
924 
925  TModelUnit yM = ctx.yy + ctx.half;
926  gl.Color4f(0.0f, 0.0f, 0.0f, m_FadeFactor); // Black
927  m_Context->DrawGreaterLessSign(xM, yM, ctx.bar_h, ctx.reverse_strand);
928  }
929 }
930 
932 {
933  IRender& gl = GetGl();
934  if (m_ShowScore && m_AlnMgr->IsRegular()) {
935  double identity = 100.0;
936  if ( !m_SeqAlign->GetNamedScore(CSeq_align::eScore_PercentIdentity, identity) ) {
937  TSeqPos align_length = m_SeqAlign->GetAlignLength();
938  int identities = (int)align_length;
939  if ( !m_SeqAlign->GetNamedScore(CSeq_align::eScore_IdentityCount, identities) ) {
940  // CScoreBuilder builder;
941  // identities = builder.GetIdentityCount(*scope, align);
942  }
943  identity = identities * 100 / align_length;
944  }
945  identity *= 0.01;
946  if (identity > 0.6) {
947  identity = 1.75 * identity - 0.75;
948  } else {
949  identity /= 2.0;
950  }
951  CRgbaColor color_max(0.78f, 0.78f, 0.78f, m_FadeFactor);
952  CRgbaColor color_min(1.0f, 0.0f, 0.0f, m_FadeFactor);
953  CRgbaColor color(CRgbaColor::Interpolate(color_max, color_min, identity));
954  if (ctx.override_color)
955  color = ctx.read_status_color;
956 
957  gl.ColorC(color);
958  m_Context->DrawQuad(ctx.seq_range.GetFrom(), ctx.yy, ctx.seq_range.GetTo(), ctx.yy + ctx.bar_h, false);
959  } else {
960  m_Context->Draw3DQuad(ctx.seq_range.GetFrom(), ctx.yy, ctx.seq_range.GetTo(), ctx.yy + ctx.bar_h, c_fg, true);
961  }
963 }
964 
965 
967  bool selected,
968  bool show_label,
969  const CRgbaColor& c_fg,
970  const CRgbaColor& c_seq,
971  const CRgbaColor& c_mis) const
972 {
973  IRender& gl = GetGl();
974 
975  int anchor = m_AlnMgr->GetAnchor();
976  int aligned_seq = m_AlnMgr->GetQuery();
977  if (aligned_seq < 0) {
978  aligned_seq = 0;
979  }
981  ctx.base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
982  ctx.base_width_curr = m_AlnMgr->GetBaseWidth(aligned_seq);
983  ctx.f = m_AlnMgr->GetSeqStart(anchor);
984  ctx.f /= ctx.base_width_anchor;
985  ctx.t = m_AlnMgr->GetSeqStop(anchor);
986  ctx.t /= ctx.base_width_anchor;
987  ctx.reverse_strand = m_AlnMgr->IsNegativeStrand(aligned_seq) != m_AlnMgr->IsNegativeStrand(anchor);
988 
989  ctx.seq_range.Set(ctx.f, ctx.t);
991  ctx.whole_range = m_AlnMgr->GetAlnRangeWithTails();
992  else
993  ctx.whole_range = ctx.seq_range;
994 
995  if (ctx.seq_range.Empty()) {
996  LOG_POST(Error
997  << "CAlignGlyph::DrawPWAlignElem: zero alignment range!");
998  return;
999  }
1000  {
1001  TModelRange inrc = m_Context->IntersectVisible(ctx.whole_range);
1002  if (inrc.Empty())
1003  return;
1004  ctx.whole_range.SetOpen((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetToOpen());
1005  inrc = m_Context->IntersectVisible(ctx.seq_range);
1006  ctx.seq_range.SetOpen((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetToOpen());
1007  }
1008 
1009  // Special colors for sra reads with errors: failed reads red,
1010  // pcr duplicates pale gray. SV-2153
1011  ctx.override_color = false;
1012  x_GetOverrideColor(ctx.override_color, ctx.read_status_color);
1013 
1014  ctx.bar_h = GetBarHeight();
1015  ctx.half = ctx.bar_h * 0.5;
1016  ctx.center_y = rcm.Bottom() - ctx.half - 1.0;
1017  ctx.yy = ctx.center_y - ctx.half;
1018 
1019  m_DisableTooltipsCaching = false;
1020 
1021  if (IsSimplified()) {
1022  x_DrawSimplified(ctx, c_fg);
1023  // Draw selection
1024  if (selected)
1025  m_Context->DrawSelection(rcm);
1026  return;
1027  }
1028 
1030  anchor, ctx.seq_range.GetFrom() * ctx.base_width_anchor, IAlnExplorer::eRight);
1032  anchor, ctx.seq_range.GetTo() * ctx.base_width_anchor, IAlnExplorer::eLeft);
1033  if (aln_r_s > aln_r_e) {
1034  swap(aln_r_s, aln_r_e);
1035  }
1036  ctx.aln_range = TSignedSeqRange(aln_r_s, aln_r_e);
1037 
1038  //cout << "seq_range:" << ctx.seq_range << ", aln_range:" << ctx.aln_range << endl;
1039 
1040  bool show_score = x_ShowScore();
1041  gl.ColorC(c_fg);
1042 
1043  TModelUnit align_len = m_Context->SeqToScreen(ctx.whole_range.GetLength());
1044  bool show_unaligned_tails = x_ShowUnalignedTails(align_len);
1045 
1046  // get tail sizes
1047  if (show_unaligned_tails) {
1048  auto aln_partial_flags = m_AlnMgr->GetPartialFlags();
1050  show_unaligned_tails = false;
1051  } else {
1052  m_AlnMgr->GetUnalignedTails(ctx.tail_5, ctx.tail_3);
1053  }
1054  }
1055  double barh = abs(m_Context->GetGlPane()->GetScaleY() * ctx.bar_h);
1056  if ((m_Context->GetScale() < 1 && !show_score) ||
1057  (show_score && m_Context->WillSeqLetterFit() && ctx.tail_3)) {
1058  TModelUnit over7 = m_Context->ScreenToSeq(7);
1059  TModelUnit over2 = m_Context->ScreenToSeq(2);
1060  TModelUnit y = ctx.yy + ctx.half;
1061  if (ctx.reverse_strand) {
1063  }
1064  else {
1066  }
1067 
1068  // ignore strand signs if bar is less that 2 pix
1069  if (barh >= 2.) {
1070 
1071  if (show_score) {
1072  // make the color for the strand indicator matches well with
1073  // the alignment bar color
1074  gl.Color4f(0.5f, 0.5f, 0.5f, m_FadeFactor);
1075  }
1076  if (ctx.reverse_strand && !(show_unaligned_tails && ctx.tail_5)) {
1077  m_Context->DrawTriangle(ctx.f - over7, y,
1078  ctx.f - over2, ctx.yy - 1, ctx.f - over2, ctx.yy + ctx.bar_h + 1);
1079  }
1080  else if (!(show_unaligned_tails && ctx.tail_3)) {
1081  m_Context->DrawTriangle(ctx.t + 1 + over7, y,
1082  ctx.t + 1 + over2, ctx.yy - 1, ctx.t + 1 + over2, ctx.yy + ctx.bar_h + 1);
1083  }
1084  }
1085  } else {
1087  } // arrows
1088 
1089  // Draw Sequence and quads for segments
1090  if (show_score) {
1091  // Disable blending for scores since they overwrite the alignment bar
1092  if (m_FadeFactor != 1.0f)
1093  gl.Disable(GL_BLEND);
1094 
1095  // do score coloration
1096  int row_num = m_AlnMgr->GetNumRows();
1097  for (int row = 0; row < row_num; ++row) {
1098  if (row == anchor) {
1099  continue; // skip master seq
1100  }
1101  if (m_Score->IsAverageable()) {
1102  x_RenderAveragableScores(ctx.yy, ctx.aln_range, ctx.seq_range, ctx.bar_h, row,
1103  ctx.override_color, ctx.read_status_color);
1104  } else {
1105  x_RenderNonAveragableScores(ctx.yy, ctx.aln_range, ctx.seq_range, ctx.bar_h, row,
1106  ctx.override_color, ctx.read_status_color);
1107  }
1108  }
1109 
1110  if (m_FadeFactor != 1.0f)
1111  gl.Enable(GL_BLEND);
1112 
1113  // if (m_Config->m_CompactMode == CAlignmentConfig::eNormal)
1114  x_DrawGaps(ctx);
1115  x_DrawInserts(ctx);
1116 
1117  // draw unaligned tails
1118  if (show_unaligned_tails) {
1119  switch (m_Config->m_UnalignedTailsMode)
1120  {
1122  break;
1124  x_DrawTailGlyphs(ctx, true, c_fg);
1125  break;
1127  x_DrawTailSequences(ctx, c_fg);
1128  break;
1129  }
1130  }
1131 
1132  } else {
1133  // Disable blending since we want overwrite here for the fading effect,
1134  // (if any) not blending with other elements
1135  if (m_FadeFactor != 1.0f)
1136  gl.Disable(GL_BLEND);
1137 
1138  x_DrawNoScoreAlign(ctx, c_fg);
1139 
1140  if (m_FadeFactor != 1.0f)
1141  gl.Enable(GL_BLEND);
1142  }
1143 
1144 
1145  // special case
1146  // reflect non-consensus splice sites for spliced-seg alignment
1147  // we only show non-consensus site when showing in genomic sequence
1148  // context, not product sequence context.
1150 
1151  if ((m_Context->WillSeqLetterFit() && ctx.base_width_anchor <= ctx.base_width_curr)
1152  || (m_Context->GetScale() <= 0.05 && ctx.base_width_anchor > ctx.base_width_curr)) {
1153  try {
1154  x_DrawAlignRowSequence(ctx.center_y, 1 - anchor, c_fg, c_seq, c_mis);
1155  } catch (const CException& e) {
1156  LOG_POST(Warning << "Can't show alignment sequence due to an error: " << e.GetMsg());
1157  }
1160  if (ctx.tail_5 > 0) {
1161  try {
1163  }
1164  catch (const CException& e) {
1165  LOG_POST(Warning << "Can't show 5' tail sequence due to an error: " << e.GetMsg());
1166  }
1167  }
1168  if (ctx.tail_3 > 0) {
1169  try {
1171  }
1172  catch (const CException& e) {
1173  LOG_POST(Warning << "Can't show 3' tail sequence due to an error: " << e.GetMsg());
1174  }
1175  }
1176  }
1177  }
1178 
1180 
1181  // Draw selection
1182  if (selected) {
1183  m_Context->DrawSelection(rcm);
1184  }
1185 }
1186 
1187 
1189 {
1190  title->erase();
1191 
1192  if ( !x_IsPWAlign()) {
1193  *title = "[Alignment] " +
1194  NStr::UIntToString(m_AlnMgr->GetNumRows()) + " sequences";
1195  return;
1196  }
1197 
1198  // pairwise align
1199  switch (type) {
1200  case CLabel::eType:
1201  case CLabel::eContent:
1203  {
1204  // display the name of the aligned sequence.
1205  int row = 1 - m_OrigAnchor;
1206  CLabel::GetLabel(m_OrigSeqAlign.GetSeq_align()->GetSeq_id(row),
1207  title, type, &m_Context->GetScope());
1208 
1209  // make title/label shorter incase it is a cSRA alignment on panfs
1210  if (title->length() > 20 && title->find("\\panfs\\") != string::npos) {
1211  size_t pos = title->find_last_of("\\");
1212  if (pos != string::npos) {
1213  *title = title->substr(pos + 1);
1214  if (title->length() > 20) {
1215  pos = title->rfind('.');
1216  if (pos != string::npos && pos > 0) {
1217  pos = title->rfind('.', pos - 1);
1218  if (pos != string::npos) {
1219  *title = title->substr(pos + 1);
1220  }
1221  }
1222  }
1223  }
1224  }
1225  };
1226  break;
1228  case CLabel::eDescription:
1229  CLabel::GetLabel(*GetOrigAlignment().GetSeq_align(),
1230  title, type, &m_Context->GetScope());
1231  break;
1232  default:
1233  break;
1234  }
1235 }
1236 
1237 
1239 {
1241  if (m_FadeFactor != 1.) {
1242  IRender& gl = GetGl();
1243  gl.Enable(GL_BLEND);
1244  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1245  }
1246 }
1247 
1249 {
1250  if (!GetVisible())
1251  return;
1252  auto vis_rect = m_Context->GetGlPane()->GetVisibleRect();
1253  if (GetTop() > vis_rect.Bottom() && GetBottom() < vis_rect.Top())
1254  return;
1255 
1256  if (x_IsPWAlign()) {
1257  ApplyFading();
1258  x_DrawPWAlign();
1259  } else {
1260  // No fade out for multiple align drawing for now. Since all the rows in
1261  // this case are inside this one glyph and drawn in a loop, we would need
1262  // to handle things a bit differently.
1263  m_FadeFactor = 1.f;
1264  x_DrawMultiAlign();
1265  }
1266 }
1267 
1268 
1270 {
1271  IRender& gl = GetGl();
1272 
1273  if (m_Intervals.empty() && x_IsPWAlign()) {
1275  }
1276 
1277  TSeqRange range = GetRange();
1278  SetWidth(range.GetLength());
1279  SetLeft(range.GetFrom());
1280 
1281  TModelUnit bar_h = GetBarHeight();
1282  if (x_IsPWAlign()) {
1284  } else {
1285  SetHeight((bar_h + kAlignRowSpace) * (m_AlnMgr->GetNumRows() - 1));
1286  }
1287 
1288  bool show_label = x_ShowLabel();
1289  // don't show labels and unaligned tails for simplified rendering
1290  if (IsSimplified() && !show_label) {
1291  return;
1292  }
1293 
1294  bool top_label = m_Config->m_LabelPos == CAlignmentConfig::ePos_Above;
1295  const CGlTextureFont& font = m_Config->m_LabelFont;
1296  int anchor = m_AlnMgr->GetAnchor();
1297  bool reverse_strand = m_AlnMgr->IsNegativeStrand(0) != m_AlnMgr->IsNegativeStrand(1);
1298  TSignedSeqPos visible_tail_5 = 0;
1299  TSignedSeqPos visible_tail_3 = 0;
1300  TSignedSeqPos tail_5 = 0;
1301  TSignedSeqPos tail_3 = 0;
1302  TSignedSeqPos base_width_curr = m_AlnMgr->GetBaseWidth(anchor == 0 ? 1 : 0);
1304 
1305  // get tail sizes
1306  if (x_ShowUnalignedTails(align_len)) {
1307 
1308  m_AlnMgr->GetUnalignedTails(tail_5, tail_3, false);
1309  m_AlnMgr->GetUnalignedTails(visible_tail_5, visible_tail_3);
1310 
1311  TModelUnit tail_len = 0;
1312  if (tail_5 > 0) {
1313  tail_len = x_GetTailWidth(tail_5, visible_tail_5, base_width_curr);
1314 
1315  SetWidth(GetWidth() + tail_len);
1316  SetLeft(GetLeft() - tail_len);
1317  }
1318  if (tail_3 > 0) {
1319  tail_len = x_GetTailWidth(tail_3, visible_tail_3, base_width_curr);
1320 
1321  SetWidth(GetWidth() + tail_len);
1322  }
1323  }
1324 
1325  if (show_label) {
1326  if (top_label) {
1327  if (x_IsPWAlign()) {
1328  // vertical space for alignment label
1329  SetHeight(GetHeight() + gl.TextHeight(&font) + 3);
1330  } else {
1331  SetHeight(GetHeight() + (gl.TextHeight(&font) + kLabelSpace_v) *
1332  (m_AlnMgr->GetNumRows() - 1));
1333  }
1334  } else { // not top label (side label)
1335  if (x_IsPWAlign()) {
1336  // horizontal space for alignment label
1337  string label;
1339  TModelUnit label_w = gl.TextWidth(&font, label.c_str());
1340  label_w = m_Context->ScreenToSeq(label_w + kLabelSpace_h);
1341  SetWidth(GetWidth() + label_w);
1342  if ( !reverse_strand ) {
1343  SetLeft(GetLeft() - label_w);
1344  }
1345  } else {
1346  TModelUnit max_label_w = 0.0;
1347  for (int row = 0; row < m_AlnMgr->GetNumRows(); ++row) {
1348  if (row == anchor) {
1349  continue; // skip master seq
1350  }
1351  string label;
1354  if (m_AlnMgr->IsNegativeStrand(anchor) !=
1355  m_AlnMgr->IsNegativeStrand(row)) {
1356  label += " (Neg)";
1357  }
1358  TModelUnit label_w = gl.TextWidth(&font, label.c_str());
1359  max_label_w = max(max_label_w, label_w);
1360  }
1361  max_label_w += kLabelSpace_h;
1362  max_label_w = m_Context->ScreenToSeq(max_label_w);
1363  SetWidth(GetWidth() + max_label_w);
1364  SetLeft(GetLeft() - max_label_w);
1365  }
1366  }
1367  }
1368 }
1369 
1370 
1372 {
1373  IRender& gl = GetGl();
1374 
1375  TModelRect rcm = GetModelRect();
1376  bool show_label = x_ShowLabel();
1377 
1378  DrawPWAlignElem(rcm, IsSelected(), show_label,
1382 
1383  if (show_label) {
1384  string label;
1386  const CGlTextureFont& l_font = m_Config->m_LabelFont;
1387  bool top_label = m_Config->m_LabelPos == CAlignmentConfig::ePos_Above;
1388  TModelUnit label_h = gl.TextHeight(&l_font);
1389  TModelRange inrc = m_Context->IntersectVisible(this);
1390  TModelUnit xM = inrc.GetFrom() + inrc.GetLength() * 0.5;
1391  TModelUnit yM = rcm.Top() + label_h + 1.0;
1392  TModelUnit max_label_width_px = m_Context->SeqToScreen(inrc.GetLength() - 1);
1393  if (max_label_width_px > 0.0) {
1394  //if (max_label_width_px > 2.0) max_label_width_px -= 2.0;
1395  TModelUnit label_width_px = gl.TextWidth(&l_font, label.c_str());
1396  if (label_width_px > max_label_width_px) {
1397  label_width_px = max_label_width_px;
1398  label = l_font.Truncate(label.c_str(), label_width_px);
1399  if ((string::npos != label.find("...")) && (label.length() <= 5))
1400  return;
1401  }
1402 
1403  if ( !top_label ) {
1404  TModelUnit t_w = m_Context->ScreenToSeq(label_width_px);
1405  bool reverse_strand = m_AlnMgr->IsNegativeStrand(0) !=
1407  yM = GetBottom() - 2.0;
1408  if (reverse_strand) {
1409  xM = inrc.GetTo() - t_w;
1410  if (inrc.GetTo() < GetRight()) {
1412  m_Context->DrawBackground( TModelRect(xM, yM + 1.0,
1413  inrc.GetTo(), yM - label_h - 1.0), 0);
1414  }
1415  } else {
1416  xM = inrc.GetFrom();
1417  if (inrc.GetFrom() > GetLeft()) {
1419  m_Context->DrawBackground( TModelRect(xM, yM + 1.0,
1420  xM + t_w, yM - label_h - 1.0), 0);
1421  }
1422  }
1423  }
1424 
1425  if (IsSelected()) {
1427  } else {
1429  }
1430  m_Context->TextOut(&l_font, label.c_str(), xM, yM, top_label);
1431  }
1432  }
1433 }
1434 
1435 
1437 {
1438  IRender& gl = GetGl();
1439 
1440  int anchor = m_AlnMgr->GetAnchor();
1441  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
1442  TSeqRange anchor_range(
1443  m_AlnMgr->GetSeqStart(anchor) / base_width_anchor,
1444  m_AlnMgr->GetSeqStop(anchor) / base_width_anchor);
1445  if (anchor_range.Empty()) {
1446  LOG_POST(Error
1447  << "CAlignGlyph::x_DrawMultiAlign: zero alignment range!");
1448  return;
1449  }
1450 
1451  TModelRange inrc = m_Context->IntersectVisible(anchor_range);
1452  anchor_range.Set((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetTo());
1453  if (anchor_range.Empty()) {
1454  return;
1455  }
1456 
1457  // Special colors for sra reads with errors: failed reads red,
1458  // pcr duplicates pale gray. SV-2153
1459  bool override_color = false;
1460  CRgbaColor read_status_color;
1461  x_GetOverrideColor(override_color, read_status_color);
1462 
1463  TSignedSeqPos aln_r_s = m_AlnMgr->GetAlnPosFromSeqPos(anchor,
1464  anchor_range.GetFrom() * base_width_anchor, IAlnExplorer::eRight);
1465  TSignedSeqPos aln_r_e = m_AlnMgr->GetAlnPosFromSeqPos(anchor,
1466  anchor_range.GetTo() * base_width_anchor, IAlnExplorer::eLeft);
1467  if (aln_r_s > aln_r_e) {
1468  swap(aln_r_s, aln_r_e);
1469  }
1470  TSignedSeqRange aln_total_range(aln_r_s, aln_r_e);
1471 
1472 
1473  TModelRect rcm = GetModelRect();
1474  TModelUnit base = rcm.Top();
1475  TModelUnit bar_h = GetBarHeight();
1476 
1477  bool show_label = x_ShowLabel();
1478  TModelUnit yy = base + 1;
1479  for (int row = 0; row < m_AlnMgr->GetNumRows(); ++row) {
1480  if (row == anchor) {
1481  continue; // skip master seq
1482  }
1483 
1484  TSignedSeqRange aln_range =
1485  aln_total_range.IntersectionWith(m_AlnMgr->GetSeqAlnRange(row));
1486  TModelUnit xM = (inrc.GetFrom() + inrc.GetTo()) * 0.5;
1487  bool reverse_strand =
1488  m_AlnMgr->IsNegativeStrand(row) !=
1489  m_AlnMgr->IsNegativeStrand(anchor);
1490 
1491  // Draw label
1492  if (show_label &&
1494  const CGlTextureFont& l_font = m_Config->m_LabelFont;
1495  yy += gl.TextHeight(&l_font);
1496  x_DrawMultiAlignLabel(row, yy);
1497  yy += kLabelSpace_v;
1498  }
1499 
1500  TModelUnit mid = yy + bar_h * 0.5;
1501  if (x_ShowScore()) {
1502  // do score coloration
1503  if (m_Score->IsAverageable()) {
1504  x_RenderAveragableScores(yy, aln_range, anchor_range, bar_h, row,
1505  override_color, read_status_color);
1506  } else {
1507  x_RenderNonAveragableScores(yy, aln_range, anchor_range, bar_h, row,
1508  override_color, read_status_color);
1509  }
1510 
1511  // color the gap differently
1512  gl.Color4f(1.0f, 0.0f, 0.0f, 1.0f);
1513  CGlAttrGuard AttrGuard(GL_LINE_BIT);
1514  gl.Disable(GL_LINE_SMOOTH);
1515 
1516  unique_ptr<IAlnSegmentIterator> p_it(
1517  m_AlnMgr->CreateSegmentIterator(row, aln_range,
1519 
1520  gl.LineWidth(2.0f);
1521  for (IAlnSegmentIterator& it = *p_it; it; ++it) {
1522  const IAlnSegment& seg = *it;
1523  if ( !(seg.GetType() & IAlnSegment::fIndel) ||
1524  !seg.GetRange().Empty() ) {
1525  continue;
1526  }
1527 
1528  TSeqPos start = m_AlnMgr->GetSeqPosFromAlnPos(anchor, seg.GetAlnRange().GetFrom());
1529  start /= base_width_anchor;
1530  TSeqPos stop = start + seg.GetAlnRange().GetLength() / base_width_anchor;
1531  m_Context->DrawLine(start, mid, stop, mid);
1532  }
1533  gl.LineWidth(1.0f);
1534 
1535  // draw inserts
1537  const TModelUnit barOff =
1538  m_AlnMgr->IsNegativeStrand(anchor) ? 1.0 : 0.0;
1539  const TModelUnit kMinLen = m_Context->ScreenToSeq(4); // 4 pixels in model units
1540 
1541  TModelUnit y1 = yy;
1542  TModelUnit y2 = yy + bar_h;
1543  p_it.reset(m_AlnMgr->CreateSegmentIterator(
1544  row, aln_range, IAlnSegmentIterator::eAllSegments));
1545 
1546  for (IAlnSegmentIterator& it = *p_it; it; ++it) {
1547  const IAlnSegment& seg = *it;
1548 
1549  if ( !(seg.GetType() & IAlnSegment::fIndel) ||
1550  seg.GetRange().Empty() ) {
1551  continue;
1552  }
1553 
1554  TSeqPos start = m_AlnMgr->GetSeqPosFromAlnPos(anchor,
1555  seg.GetAlnRange().GetTo(),
1557  start /= base_width_anchor;
1559  len = max(len, kMinLen);
1560  TModelUnit x1 = start + barOff - len * 0.5;
1561  TModelUnit x2 = x1 + len;
1562 
1563  m_Context->DrawLine_NoAA(start + barOff, y1, start + barOff, y2);
1564  m_Context->DrawLine_NoAA(x1, y1, x2, y1);
1565  m_Context->DrawLine_NoAA(x1, y2, x2, y2);
1566  }
1567  } else { // use default scheme
1569 
1570  // draw connection line in the middle
1571  m_Context->DrawLine_NoAA(anchor_range.GetFrom(), mid, anchor_range.GetTo(), mid);
1572  TIntervals intervals;
1573  x_CalcIntervals(intervals, row);
1574  ITERATE(TIntervals, it, intervals) {
1575  m_Context->Draw3DQuad(it->GetFrom(), yy, it->GetTo(), yy + bar_h, CRgbaColor(m_Config->m_FG, m_FadeFactor), true);
1576  }
1577  }
1578 
1579  if (m_Context->WillSeqLetterFit()) {
1580  try {
1581  x_DrawAlignRowSequence(mid, row,
1585  } catch (CException& e) {
1586  LOG_POST(Warning << "Can't show alignment sequence due to an error: "
1587  << e.GetMsg());
1588  }
1589 
1590  } else if (m_Context->WillLabelFit(inrc)) {
1591  // draw strand indicators
1592  // do not draw strand when sequence is shown
1593  gl.Color4f(0.0f, 0.0f, 0.0f, m_FadeFactor); // Black
1594  gl.Color4f(0.0f, 0.0f, 0.0f, m_FadeFactor); // Black
1595  TModelUnit fs = gl.TextHeight(&(m_Config->m_SeqFont)) - 1;
1596  TModelUnit yM = yy + fs + 1;
1597  char strandLabel[2] = {'>', '\0'};
1598  if (m_Context->IsHorizontal()){
1599  if (m_Context->IsFlippedStrand()){
1600  strandLabel[0] = reverse_strand ? '>' : '<';
1601  } else {
1602  strandLabel[0] = reverse_strand ? '<' : '>';
1603  }
1604  } else {
1605  if (m_Context->IsFlippedStrand()){
1606  strandLabel[0] = reverse_strand ? '<' : '>';
1607  } else {
1608  strandLabel[0] = reverse_strand ? '>' : '<';
1609  }
1610  }
1611  m_Context->TextOut(&m_Config->m_SeqFont, strandLabel, xM, yM, true);
1612  }
1613 
1614  if (show_label &&
1616  const CGlTextureFont& l_font = m_Config->m_LabelFont;
1617  TModelUnit yM = yy + gl.TextHeight(&l_font);
1618  x_DrawMultiAlignLabel(row, yM);
1619  }
1620  // advance to next row: 1 pixel between
1621  yy += bar_h + kAlignRowSpace;
1622  }
1623 
1624  // Draw selection
1625  if (IsSelected()) {
1626  m_Context->DrawSelection(rcm);
1627  }
1628 }
1629 
1630 
1632 {
1633  IRender& gl = GetGl();
1634 
1635  string label;
1639  m_AlnMgr->IsNegativeStrand(row)) {
1640  label += " (Neg)";
1641  }
1642  const CGlTextureFont& l_font = m_Config->m_LabelFont;
1643 
1644  TModelRange inrc = m_Context->IntersectVisible(this);
1645  TModelUnit max_label_width_px = m_Context->SeqToScreen(inrc.GetLength());
1646  TModelUnit label_w = gl.TextWidth(&l_font, label.c_str());
1647  if (label_w > max_label_width_px) {
1648  label_w = max_label_width_px;
1649  label = l_font.Truncate(label.c_str(), max_label_width_px);
1650  }
1651  bool top_label = m_Config->m_LabelPos == CAlignmentConfig::ePos_Above;
1652  TModelUnit xM = (inrc.GetFrom() + inrc.GetTo()) * 0.5;
1653  if ( !top_label ) {
1654  xM = inrc.GetFrom();
1655  if (inrc.GetFrom() > GetLeft()) {
1657  label_w = m_Context->ScreenToSeq(label_w);
1658  m_Context->DrawBackground( TModelRect(xM, y + 1.0,
1659  xM + label_w, y - gl.TextHeight(&l_font) - 1.0), 0);
1660  }
1661  }
1662 
1663  if (IsSelected()) {
1665  } else {
1667  }
1668  m_Context->TextOut(&l_font, label.c_str(), xM, y, top_label);
1669 }
1670 
1671 
1673  int row,
1674  const CRgbaColor& c_fg,
1675  const CRgbaColor& c_seq,
1676  const CRgbaColor& c_mis) const
1677 {
1678  IRender& gl = GetGl();
1680 
1681  int anchor = m_AlnMgr->GetAnchor();
1682  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
1683  TSeqPos base_width_curr = m_AlnMgr->GetBaseWidth(row);
1684  TSeqRange anchor_range(
1685  m_AlnMgr->GetSeqStart(anchor) / base_width_anchor,
1686  m_AlnMgr->GetSeqStop(anchor) / base_width_anchor);
1687  TModelRange inrc = m_Context->IntersectVisible(anchor_range);
1688  anchor_range.Set((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetTo());
1689  if (anchor_range.Empty()) {
1690  return;
1691  }
1692  const CBioseq_Handle& mhndl = m_AlnMgr->GetBioseqHandle(anchor);
1693  if (!mhndl)
1694  return;
1695  const CBioseq_Handle& hndl = m_AlnMgr->GetBioseqHandle(row);
1696  if (!hndl)
1697  return;
1698 
1699  TSignedSeqPos aln_r_s = m_AlnMgr->GetAlnPosFromSeqPos(anchor,
1700  anchor_range.GetFrom() * base_width_anchor, IAlnExplorer::eRight);
1701  TSignedSeqPos aln_r_e = m_AlnMgr->GetAlnPosFromSeqPos(anchor,
1702  anchor_range.GetTo() * base_width_anchor, IAlnExplorer::eLeft);
1703  if (aln_r_s > aln_r_e) {
1704  swap(aln_r_s, aln_r_e);
1705  }
1706  TSignedSeqRange aln_range(aln_r_s, aln_r_e);
1707 
1708  if (aln_range.GetFrom() > 2) {
1709  aln_range.SetFrom(aln_range.GetFrom() - 3);
1710  }
1711 
1712  gl.ColorC(c_fg);
1713 
1714  bool reverse_strand = m_AlnMgr->IsNegativeStrand(row) !=
1715  m_AlnMgr->IsNegativeStrand(anchor);
1716 
1717  unique_ptr<IAlnSegmentIterator> p_it(
1719  aln_range, IAlnSegmentIterator::eSkipGaps));
1720 
1721  bool ab = mhndl.IsAa();
1722  bool rb = hndl.IsAa();
1723  CSeqVector ms_vec =
1725  CSeqVector s_vec =
1727 
1728  EAlignSpacing spacing(eOne2One);
1729  if (!ab && rb) spacing = eOne2Three;
1730  if (ab && !rb) spacing = eThree2One;
1731 
1732  for ( IAlnSegmentIterator& it(*p_it); it; ++it ) {
1733  const IAlnSegment& seg = *it;
1734 
1735  // We need to deal with some tricky genomic-to-protein alignments
1736  // described in both GB-2336 and GB-2324. Sometimes, the insertions
1737  // on the protein sequence row are one-(nucleotide)-base insertions.
1738  // That means two nucleiotide bases on genomic sewquence correspond
1739  // to one residue on the protein sequence at that insertion postion.
1740  // Normally, it one-to-three or three-to-one relation. That introduces
1741  // all sort of troubles including:
1742  // - showing correct sequence
1743  // - positioning the sequence correctly,
1744  // - retrieving the correct chunk of sequences for both protein
1745  // translation and protein-to-genomic comparison
1746 
1747  TSeqPos start = seg.GetRange().GetFrom();
1748  TSeqPos stop = seg.GetRange().GetTo();
1749  TSeqPos sStart = (TModelUnit)m_AlnMgr->GetSeqPosFromAlnPos(anchor, seg.GetAlnRange().GetFrom());
1750  TSeqPos sStop = (TModelUnit)m_AlnMgr->GetSeqPosFromAlnPos(anchor, seg.GetAlnRange().GetTo());
1751 
1752 
1753  TSeqPos frame_shift_f = start % base_width_curr;
1754  TSeqPos frame_shift_t = 2 - stop % base_width_curr;
1755  if (base_width_anchor == 3) {
1756  frame_shift_f = sStart % base_width_anchor;
1757  frame_shift_t = 2 - sStop % base_width_anchor;
1758  }
1759  if (sStart > sStop) {
1760  swap(sStart, sStop);
1761  swap(frame_shift_f, frame_shift_t);
1762  }
1763  stop /= base_width_curr;
1764  start /= base_width_curr;
1765  sStart /= base_width_anchor;
1766  sStop /= base_width_anchor;
1767 
1768  TSeqPos seg_start = sStart;
1769  TSeqPos seg_stop = sStop;
1770 
1771  // Make sure nucleotide coordinate aligns protein codon's
1772  // starting/ending base. We need to do protein
1773  if (spacing == eOne2Three) {
1774  // top/anchor sequence is nucleotide, and and aligned sequence
1775  // is protein.
1776  sStop += frame_shift_t;
1777  sStart -= frame_shift_f;
1778  } else if (spacing == eThree2One) {
1779  // make sure it aligns codon's starting base
1780  stop += frame_shift_t;
1781  start -= frame_shift_f;
1782  }
1783 
1784  // check if sStop is larger than the sequence lenght
1785  sStop = min(sStop, mhndl.GetBioseqLength());
1786 
1787  try {
1788 
1789  string seq, mseq, tmp_seq, visible_seq;
1790  s_vec.GetSeqData (start, stop + 1, tmp_seq);
1791  ms_vec.GetSeqData(sStart, sStop + 1, mseq);
1792  visible_seq = tmp_seq;
1793 
1794  if (reverse_strand) {
1795 
1796  if (rb) {
1797  // protein sequence, just reverse it
1798  CSeqManip::Reverse(tmp_seq, CSeqUtil::e_Iupacaa, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
1799  visible_seq = seq;
1800  } else {
1801  // nucleotide sequence, get reverse and complement
1802  CSeqManip::ReverseComplement(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), seq);
1803 
1804  if (m_Context->IsFlippedStrand()) {
1805  CSeqManip::Reverse(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), visible_seq);
1806  } else {
1807  visible_seq = seq;
1808  }
1809 
1810  }
1811 
1812  } else {
1813  if (!rb && m_Context->IsFlippedStrand()) {
1814  CSeqManip::Complement(tmp_seq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(tmp_seq.length()), visible_seq);
1815  }
1816  swap(seq, tmp_seq);
1817  }
1818  string translated_seq;
1819  switch (spacing) {
1820  case eOne2Three:
1821  {
1822  string seq_candidate = mseq;
1823  if (reverse_strand) {
1824  CSeqManip::ReverseComplement(mseq, CSeqUtil::e_Iupacna, 0, static_cast<TSeqPos>(mseq.length()), seq_candidate);
1825  }
1826  CGenetic_code gcode;
1827  gcode.SetId(m_AlnMgr->GetGenCode(anchor));
1828  CSeqTranslator::Translate(seq_candidate, translated_seq, CSeqTranslator::fIs5PrimePartial, &gcode);
1829  if (reverse_strand) {
1830  // don't use the same string as the input and output string.
1831  CSeqManip::Reverse(translated_seq, CSeqUtil::e_Iupacaa, 0, static_cast<TSeqPos>(translated_seq.length()), tmp_seq);
1832  translated_seq = tmp_seq;
1833  }
1834  }
1835  break;
1836  case eThree2One:
1837  {
1838  auto r = seg.GetAlnRange();
1839  r.SetFrom(r.GetFrom() - frame_shift_f);
1840  r.SetTo(r.GetTo() + frame_shift_t);
1841  m_AlnMgr->GetAlnSeqString(row, seq, r);
1842  CGenetic_code gcode;
1843  gcode.SetId(m_AlnMgr->GetGenCode(row));
1844  CSeqTranslator::Translate(seq, translated_seq, CSeqTranslator::fIs5PrimePartial, &gcode);
1845  }
1846  break;
1847  default:
1848  break;
1849  }
1850 
1851  char bases[2];
1852  bases[1] = '\0';
1853  TVPUnit font_w =
1854  (TVPUnit)(gl.TextWidth(&(m_Config->m_SeqFont),"G") * 0.5f);
1855  TModelUnit addon = 0.5 - m_Context->ScreenToSeq(font_w);
1856 
1857  TSeqPos start_base = frame_shift_f % base_width_anchor;
1858  TSeqPos stop_base = min(stop - start + 1 - frame_shift_t % base_width_anchor,
1859  (TSeqPos)seq.length());
1860 
1861  // Draw characters (actg)
1862  for (TSeqPos bp = start_base; bp < stop_base; bp++) {
1863  TModelUnit pos = 0;
1864  bool match = true;
1865  switch (spacing) {
1866  case eOne2One:
1867  pos = sStart + bp + addon;
1868  match = bp < seq.size() && bp < mseq.size()
1869  && seq[bp] == mseq[bp];
1870  break;
1871  case eOne2Three:
1872  pos = sStart + bp * 3 + addon + 1;
1873  match = bp < seq.size() && bp < translated_seq.size()
1874  && seq[bp] == translated_seq[bp];
1875  break;
1876  case eThree2One: {
1877  pos = sStart + bp * kPWAlignPackLevel + addon - kPWAlignPackLevel;
1878  int bp_pos = bp / 3;
1879  match = bp_pos < seq.size() && bp_pos < translated_seq.size()
1880  && mseq[bp_pos] == translated_seq[bp_pos];
1881  break;
1882  }
1883  default:
1884  break;
1885  }
1886  if (pos < (seg_start - 0.5))
1887  continue;
1888  if (pos > (seg_stop + 1))
1889  continue;
1890 
1891  // Highlight mismatch?
1892  match ? gl.ColorC(c_seq) : gl.ColorC(c_mis);
1893  if (match && !m_Config->m_ShowIdenticalBases) {
1894  CRgbaColor c = c_seq;
1895  c.Lighten(0.65f);
1896  gl.ColorC(c);
1897  TModelUnit bh = GetBarHeight();
1898  m_Context->DrawDisk2(TModelPoint(pos, center_y), (bh / 2.0) + 0.5, c);
1899  }
1900  else {
1901  // set scoring if avaliable
1902  if (m_Score && m_Score->HasScores()) {
1903  if (m_Score->GetSupportedColorTypes() & IScoringMethod::fForeground) {
1904  unique_ptr<IAlnScoreIterator> score_iter(m_Score->GetScoreIterator(row));
1905  score_iter->MoveTo(bp);
1906  IScoringMethod::TScore score = score_iter->GetAttr();
1907  CRgbaColor cl = m_Score->GetColorForScore(score,
1909  cl.SetAlpha(m_FadeFactor);
1910  gl.ColorC(cl); // use scoreing color
1911  }
1912  else {
1913  gl.ColorC(c_seq); // use default color
1914  }
1915  }
1916 
1917  bases[0] = visible_seq[bp];
1918 
1919  m_Context->TextOut(&m_Config->m_SeqFont, bases,
1920  pos, center_y + fs * 0.5, false);
1921  }
1922  } // for TSeqPos
1923  }
1924  catch (CException&) {
1925  /// ignore exceptions - these are all objmgr related
1926  }
1927  } // for i = 0
1928 
1929  if (IsLastRow()) {
1930  gl.ColorC(CRgbaColor(c_seq, 1.0f));
1931  const char* long_msg = (GetTearline() < eMaxRowLimit) ?
1932  "Alignment rows truncated for 'Adaptive' display - select 'Show All' to see more"
1933  : "The number of alignment rows exceeds the supported limit";
1934  const char* short_msg = (GetTearline() < eMaxRowLimit) ?
1935  "Select 'Show All' to see all alignments"
1936  : "Number of rows exceeds limit";
1937  const char* char_msg = "X";
1938  TModelUnit long_msg_width = gl.TextWidth(&m_Config->m_LabelFont, long_msg);
1939  TModelUnit short_msg_width = gl.TextWidth(&m_Config->m_LabelFont, short_msg);
1940  TModelUnit char_msg_width = gl.TextWidth(&m_Config->m_LabelFont, char_msg);
1941 
1943  TModelUnit seq_char_width = m_Context->ScreenToSeq(char_msg_width);
1944 
1945  const char* msg = NULL;
1946  TModelUnit msg_width = 0.0;
1947 
1948  if (width > long_msg_width) {
1949  msg = long_msg;
1950  msg_width = long_msg_width;
1951  }
1952  else if (width > short_msg_width) {
1953  msg = short_msg;
1954  msg_width = short_msg_width;
1955  }
1956  else if (width > char_msg_width) {
1957  msg = char_msg;
1958  msg_width = char_msg_width;
1959  }
1960  else {
1961  }
1962 
1963  TModelUnit msg_spacing = char_msg_width * 4.0;
1964 
1965  if (msg != NULL) {
1966  // Only room for the message - no filler on the sides
1967  if (width < msg_width + msg_spacing*2.0) {
1968  TModelUnit w = (width - msg_width)*0.5;
1970  GetLeft() + m_Context->ScreenToSeq(w), center_y + fs * 0.5, false);
1971  }
1972  // Room for message + filler:
1973  else {
1974  TModelUnit w = (width - msg_width)*0.5;
1975  TModelUnit seq_w = m_Context->ScreenToSeq(w);
1976 
1978  GetLeft() + m_Context->ScreenToSeq(w), center_y + fs * 0.5, false);
1979 
1980  // Draw jagged lines on either side of the message
1981  gl.Color3f(0.5, 0.5, 0.5f);
1982  vector<TModelPoint> pts;
1983  bool bottom_y = true;
1984  TModelUnit pos = GetLeft();
1985  while (pos < GetLeft() + seq_w - seq_char_width) {
1986  if (bottom_y)
1987  pts.push_back(TModelPoint(pos, center_y + fs * 0.5));
1988  else
1989  pts.push_back(TModelPoint(pos, center_y - fs * 0.5));
1990 
1991  bottom_y = !bottom_y;
1992  pos += seq_char_width;
1993  }
1994  m_Context->DrawLineStrip(pts);
1995  pts.clear();
1996 
1997  bottom_y = true;
1998  pos = GetRight();
1999  while (pos > GetRight() - (seq_w - seq_char_width)) {
2000  if (bottom_y)
2001  pts.push_back(TModelPoint(pos, center_y + fs * 0.5));
2002  else
2003  pts.push_back(TModelPoint(pos, center_y - fs * 0.5));
2004 
2005  bottom_y = !bottom_y;
2006  pos -= seq_char_width;
2007  }
2008  m_Context->DrawLineStrip(pts);
2009  }
2010  }
2011  }
2012 }
2013 
2014 // Scoring structures/functions start
2015 /// represents a pixel with a score, if several intervals cover a pixel, the interval
2016 /// with the maximum coverage will "own" the pixel (i.e. the pixel will be colored
2017 /// according to the score of this interval)
2018 /// This is used for non-averageable scores.
2019 struct SScPix {
2020  float m_Score; /// score assigned to the pixel
2021  float m_MaxCoverage; /// fraction of the pixel corresponding to the m_Score
2022  bool m_Gap; /// true if this is a gap interval
2023 
2024  bool operator==(const SScPix& other) const
2025  {
2026  return m_Score == other.m_Score &&
2027  m_MaxCoverage == other.m_MaxCoverage &&
2028  m_Gap == other.m_Gap;
2029  }
2030 };
2031 
2032 
2033 /// a pixel with the Max coverage (fraction) overrides all attributes
2034 static void FSetPixMaxCoverage(SScPix& dst, const SScPix& src,
2035  float fraction, bool)
2036 {
2037  if(fraction > dst.m_MaxCoverage) {
2038  dst.m_Score = src.m_Score;
2039  dst.m_Gap = src.m_Gap;
2040  dst.m_MaxCoverage = fraction;
2041  }
2042 }
2043 
2044 
2046  TSignedSeqRange aln_range,
2047  TSeqRange seq_range,
2048  TModelUnit height,
2049  int row,
2050  bool override_color,
2051  const CRgbaColor& read_status_color) const
2052 {
2053  IRender& gl = GetGl();
2054 
2055  TModelUnit fromM = (TModelUnit)seq_range.GetFrom();
2056  TModelUnit toM = (TModelUnit)seq_range.GetToOpen();
2057  int anchor = m_AlnMgr->GetAnchor();
2058  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
2059 
2060  // coloration range in the viewport coordinate system
2061  TVPUnit scoreStart = m_Context->SeqToScreenX(fromM);
2062  TVPUnit scoreEnd = m_Context->SeqToScreenX(toM);
2063 
2064  typedef CRasterizer<SScPix> TR;
2065  TR rasterizer(scoreStart, scoreEnd, fromM, toM);
2066  SScPix pix = { 0.0f, 0.0f, false };
2067 
2068  unique_ptr<IAlnScoreIterator> score_iter(m_Score->GetScoreIterator(row));
2069  IAlnScoreIterator& it = *score_iter;
2070  unique_ptr<IAlnSegmentIterator> p_it(m_AlnMgr->CreateSegmentIterator(row,
2071  aln_range, IAlnSegmentIterator::eSkipGaps));
2072 
2073  IAlnSegmentIterator& aln_seg_it(*p_it);
2074  while (aln_seg_it && it) {
2075  const IAlnSegment& seg = *aln_seg_it;
2076  const TSignedSeqRange& r = seg.GetAlnRange();
2077 
2078  TSignedSeqPos start1 = r.GetFrom();
2079  TSignedSeqPos stop1 = r.GetTo();
2080  TSignedSeqPos start2 = it.GetFrom();
2081  TSignedSeqPos stop2 = it.GetTo();
2082 
2083  while (it && start1 > stop2) {
2084  ++it;
2085  start2 = it.GetFrom();
2086  stop2 = it.GetTo();
2087  }
2088 
2089  if (start1 > stop2) {
2090  break;
2091  }
2092 
2093  int from, to;
2094  from = std::max<int>(start1, start2);
2095  to = std::min<int>(stop1, stop2);
2096 
2097  TModelUnit act_from = m_AlnMgr->GetSeqPosFromAlnPos(anchor, from);
2098  act_from /= base_width_anchor;
2099  TModelUnit act_to = m_AlnMgr->GetSeqPosFromAlnPos(anchor, to);
2100  act_to /= base_width_anchor;
2101  if (act_from > act_to) {
2102  swap(act_from, act_to);
2103  }
2104 
2105  if (act_from <= act_to) {//! seg.IsGap()) {
2106  pix.m_Score = it.GetAttr();
2107  pix.m_Gap = seg.IsGap();
2108  rasterizer.AddInterval(act_from, act_to + 1.0 / base_width_anchor, pix, FSetPixMaxCoverage);
2109  }
2110 
2111  /// advance iterators
2112  if (to == stop1) {
2113  ++aln_seg_it;
2114  }
2115  if (to == stop2) {
2116  ++it;
2117  }
2118  }
2119 
2120  // Rendering
2121  const TR::TRaster& raster = rasterizer.GetRaster();
2122  static float eps = 0.0001f;
2123  double shift_x = scoreStart;
2124 
2125  gl.PushMatrix();
2126  gl.Scalef(m_Context->GetScale(), 1.0f, 1.0f);
2127  for (size_t i = 0; i < raster.size(); ) {
2128  double start = i + shift_x;
2129  const SScPix& sc_pix = raster[i];
2130  while (++i < raster.size() && raster[i] == sc_pix);
2131 
2132  if (sc_pix.m_MaxCoverage > eps) {
2133  CRgbaColor color = m_Score->GetColorForScore(
2135  if (override_color)
2136  color = read_status_color;
2137 
2138  // Lighten color if we are fading out (instead of using
2139  // blending which we don't want for the rectanges which should
2140  // overwrite (not blend with) what is behind them.
2141  if (m_FadeFactor < 1.0f)
2142  color.Lighten(1.0 - m_FadeFactor);
2143  gl.ColorC(color);
2144 
2145  // vertical offset from the border of the alignment band
2146  // to the border of gap band
2147  int GapOffset = 2;
2148  int off_y = sc_pix.m_Gap ? GapOffset : 0;
2149 
2150  double x2 = i + shift_x;
2151  if (start == x2) {
2152  gl.Begin(GL_LINES);
2153  gl.Vertex2d(start, yy + off_y);
2154  gl.Vertex2d(start, yy + height - off_y);
2155  gl.End();
2156  } else {
2157  gl.Rectd(start, yy + off_y, x2, yy + height - off_y);
2158  }
2159  }
2160  }
2161  gl.PopMatrix();
2162 }
2163 
2164 
2165 struct SScPix2 {
2166  float m_IntScore;
2167  float m_IntLen;
2168  float m_GapScore;
2169  float m_GapLen;
2170  float m_MinScore;
2171  bool m_Init;
2172 
2173  bool operator==(const SScPix2& other) const
2174  {
2175  return m_IntScore == other.m_IntScore && m_IntLen == other.m_IntLen &&
2176  m_GapScore == other.m_GapScore && m_GapLen == other.m_GapLen &&
2177  m_MinScore == other.m_MinScore;
2178  }
2179 };
2180 
2181 
2182 /// accumulate weighted scores
2183 static void FSetPix2(SScPix2& dst, const SScPix2& src, float fraction, bool long_seg)
2184 {
2185  dst.m_IntScore += src.m_IntScore * fraction;
2186  dst.m_IntLen += src.m_IntLen * fraction;
2187  dst.m_GapScore += src.m_GapScore * fraction;
2188  dst.m_GapLen += src.m_GapLen * fraction;
2189 
2190  if( ! long_seg) {
2191  // only for small segments
2192  static const float eps = 0.00001f;
2193  if( ! dst.m_Init) {
2194  if(src.m_IntLen > eps) {
2195  dst.m_MinScore = src.m_IntScore;
2196  dst.m_Init = true;
2197  } else if(src.m_GapLen > eps) {
2198  dst.m_MinScore = src.m_GapScore;
2199  dst.m_Init = true;
2200  }
2201  } else {
2202  if(src.m_IntLen > eps) {
2203  dst.m_MinScore = min(dst.m_MinScore, src.m_IntScore);
2204  }
2205  if(src.m_GapLen > eps) {
2206  dst.m_MinScore = min(dst.m_MinScore, src.m_GapScore);
2207  }
2208  }
2209  }
2210 }
2211 
2212 
2214  TSignedSeqRange aln_range,
2215  TSeqRange seq_range,
2216  TModelUnit height,
2217  int row,
2218  bool override_color,
2219  const CRgbaColor& read_status_color) const
2220 {
2221  if (seq_range.Empty())
2222  return;
2223 
2224  IRender& gl = GetGl();
2225 
2226  TModelUnit fromM = (TModelUnit)seq_range.GetFrom();
2227  TModelUnit toM = (TModelUnit)seq_range.GetToOpen();
2228  int anchor = m_AlnMgr->GetAnchor();
2229  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
2230 
2231  // coloration range in the viewport coordinate system
2232  TVPUnit scoreStart = m_Context->SeqToScreenXInModelUnit(fromM);
2233  TVPUnit scoreEnd = TVPUnit(ceil(m_Context->SeqToScreenXInModelUnit(toM)));
2234 
2235  typedef CRasterizer<SScPix2> TR;
2236  TR rasterizer(scoreStart, scoreEnd, fromM, toM);
2238  unique_ptr<IAlnScoreIterator> score_it(m_Score->GetScoreIterator(row));
2239  IAlnScoreIterator& it = *score_it;
2240  unique_ptr<IAlnSegmentIterator> p_it(m_AlnMgr->CreateSegmentIterator(row,
2241  aln_range, IAlnSegmentIterator::eAllSegments));
2242 
2243  IAlnSegmentIterator& aln_seg_it(*p_it);
2244  while (aln_seg_it && it) {
2245  const IAlnSegment& seg = *aln_seg_it;
2246  const TSignedSeqRange& r = seg.GetAlnRange();
2247 
2248  TSignedSeqPos start1 = r.GetFrom();
2249  TSignedSeqPos stop1 = r.GetTo();
2250  TSignedSeqPos start2 = it.GetFrom();
2251  TSignedSeqPos stop2 = it.GetTo();
2252 
2253  while (it && start1 > stop2) {
2254  ++it;
2255  if (it) {
2256  start2 = it.GetFrom();
2257  stop2 = it.GetTo();
2258  }
2259  }
2260 
2261  if (start1 > stop2) {
2262  break;
2263  }
2264 
2265  TSignedSeqPos from, to;
2266  from = std::max<int>(start1, start2);
2267  to = std::min<int>(stop1, stop2);
2268 
2269  SScPix2 pix = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, false };
2271  act_from /= base_width_anchor;
2273  act_to /= base_width_anchor;
2274  if (act_from > act_to) {
2275  swap(act_from, act_to);
2276  }
2277  if (act_from <= act_to && act_from <=toM) {
2278  if (seg.IsAligned()) {
2279  pix.m_IntLen = 1.;
2280  pix.m_IntScore = it.GetAttr();
2281  if (pix.m_IntScore < value_limits.GetFrom())
2282  value_limits.SetFrom(pix.m_IntScore);
2283  else if (pix.m_IntScore > value_limits.GetTo())
2284  value_limits.SetTo(pix.m_IntScore);
2285  rasterizer.AddInterval(act_from, act_to + 1.0 / base_width_anchor, pix, FSetPix2);
2286  //} else if (seg.IsIndel()) {
2287  //++aln_seg_it;
2288  //continue;
2289  } else if (seg.IsIndel() || seg.IsGap()) {
2290  int len = (act_to - act_from) + 1;// / base_width_anchor;
2291  if (m_Context->SeqToScreen(len) <= 1.5) {
2292  pix.m_GapLen = 1.;
2293  pix.m_GapScore = it.GetAttr();
2294  rasterizer.AddInterval(act_from, act_to + 1.0 / base_width_anchor, pix, FSetPix2);
2295  }
2296  }
2297  }
2298 
2299  /// advance iterators
2300  if (to == stop1) {
2301  ++aln_seg_it;
2302  }
2303  if (to == stop2) {
2304  ++it;
2305  }
2306  }
2307 
2308  // Rendering
2309  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2310 
2311  const TR::TRaster& raster = rasterizer.GetRaster();
2312 
2313  double barh = abs(m_Context->GetGlPane()->GetScaleY() * height);
2314 
2315  double shift_x = scoreStart;
2316  static const float eps = 0.001f;
2317  float value_scale = value_limits.GetTo() - value_limits.GetFrom();
2318  if (value_scale <= 0)
2319  value_scale = 1;
2320  gl.PushMatrix();
2321  gl.Scalef(m_Context->GetScale(), 1.0f, 1.0f);
2322  for (size_t i = 0; i < raster.size(); ) {
2323  double start = i + shift_x;
2324  const SScPix2& sc_pix = raster[i];
2325  while (++i < raster.size() && raster[i] == sc_pix);
2326  CRgbaColor color = m_Score->GetColorForScore(sc_pix.m_MinScore, IScoringMethod::fBackground);
2327  bool draw = false;
2328  if (sc_pix.m_IntLen > eps) {
2329  draw = true;
2330  float sc = sc_pix.m_IntScore / sc_pix.m_IntLen;
2331  //float sc = min(1.0f, float(sc_pix.m_IntScore / sc_pix.m_IntLen));
2332  color = override_color ?
2333  read_status_color : m_Score->GetColorForScore(sc, IScoringMethod::fBackground);
2334  if (sc_pix.m_Init) {
2335  sc = min(1.0f, ((sc - value_limits.GetFrom()) / value_scale));
2336  CRgbaColor color2 = m_Score->GetColorForScore(sc_pix.m_MinScore,
2338  float alpha = 1.0f - sc * 0.75f;
2339  color = CRgbaColor::Interpolate(color2, color, alpha);
2340  }
2341  // m_GapLen is and insertion length
2342  if (sc_pix.m_GapLen > eps) {
2343  //float sc = min(1.0f, sc_pix.m_GapScore / sc_pix.m_GapLen);
2344  // make lower score more prominent
2345  float alpha = min(1.0f, 0.25f + sc_pix.m_GapLen * 0.75f);
2347  }
2348  }
2349  if (draw) {
2350  color.Lighten(1.0 - color.GetAlpha() * m_FadeFactor);
2351  gl.Color4d(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha()*m_FadeFactor);
2352  double x2 = i + shift_x;
2353  if (start == x2) {
2354  gl.Begin(GL_LINES);
2355  gl.Vertex2d(start, yy);
2356  gl.Vertex2d(start, yy + height);
2357  gl.End();
2358  } else {
2359 
2360  if (barh >= 2.) {
2361  gl.Rectd(start, yy, x2, yy + height);
2362  } else {
2363  // if bar height is less than 2px
2364  // blue thin line that goes through the whole
2365  // alignment glyph occasianally gets visible
2366  // when rendered by MESA (blue band issue).
2367  // Setting linewidth to 2 fixes that
2368 
2369  gl.LineWidth(2);
2370  gl.Begin(GL_LINES);
2371  gl.Vertex2d(start, yy);
2372  gl.Vertex2d(x2, yy);
2373  gl.End();
2374  gl.LineWidth(1.);
2375  }
2376  }
2377  }
2378 
2379  }
2380  gl.PopMatrix();
2381 }
2382 
2383 static float kMinSegDistance = 1.5f;
2384 
2385 void CAlignGlyph::x_CalcIntervals(TIntervals& intervals, int target_row) const
2386 {
2387  intervals.clear();
2388 
2389  int anchor = m_AlnMgr->GetAnchor();
2390  TSeqPos base_width_anchor = m_AlnMgr->GetBaseWidth(anchor);
2391  TSeqRange r(
2392  m_AlnMgr->GetSeqStart(anchor) / base_width_anchor,
2393  m_AlnMgr->GetSeqStop(anchor) / base_width_anchor);
2394 
2395  if (r.Empty()) {
2396  LOG_POST(Error
2397  << "CAlignGlyph::x_CalcIntervals: zero alignment range!");
2398  return;
2399  }
2400 
2401  {
2403  if (inrc.Empty())
2404  return;
2405  //r.SetOpen((TSeqPos)inrc.GetFrom(), (TSeqPos)inrc.GetToOpen());
2406  //if (r.Empty())
2407  // return;
2408  }
2409  // optimization
2410  // Only use the total range if the size is small
2411  if (IsSimplified()) {
2412  intervals.push_back(r);
2413  return;
2414  }
2416  anchor, r.GetFrom() * base_width_anchor, IAlnExplorer::eRight);
2418  anchor, r.GetTo() * base_width_anchor, IAlnExplorer::eLeft);
2419  if (aln_r_s > aln_r_e) {
2420  swap(aln_r_s, aln_r_e);
2421  }
2422  CRange<TSignedSeqPos> aln_range(aln_r_s, aln_r_e);
2423 
2424  int row = target_row;
2425  if (row < 0)
2426  row = max(0, 1 - anchor);
2427 
2428  unique_ptr<IAlnSegmentIterator> p_it(m_AlnMgr->CreateSegmentIterator(row,
2429  aln_range,
2431  TSeqRange rrr;
2432  for ( IAlnSegmentIterator& it(*p_it); it; ++it ) {
2433  const IAlnSegment& seg = *it;
2434  if (seg.GetRange().Empty())
2435  continue;
2436  if (!seg.IsAligned() || seg.IsIndel())
2437  continue;
2438  const TSignedSeqRange& aln_r = seg.GetAlnRange();
2439  if (aln_r.Empty())
2440  continue;
2441  TSeqPos start = m_AlnMgr->GetSeqPosFromAlnPos(anchor, aln_r.GetFrom());
2442  start /= base_width_anchor;
2443  TSeqPos stop = m_AlnMgr->GetSeqPosFromAlnPos(anchor, aln_r.GetTo());
2444  stop /= base_width_anchor;
2445  if (start > stop)
2446  swap(start, stop);
2447  bool add = true;
2448  if (!intervals.empty()) {
2449  TModelUnit dist = m_Context->SeqToScreen(start - intervals.back().GetTo());
2450  if (dist < kMinSegDistance) {
2451  intervals.back().SetTo(stop);
2452  add = false;
2453  }
2454  }
2455  if (add)
2456  intervals.push_back( TSeqRange(start, stop) );
2457  }
2458 }
2459 
2461 {
2462  bool shown = false;
2463  if (m_Config->m_ShowLabel &&
2467  if (m_Context->WillLabelFit(r)) {
2468  shown = true;
2469  }
2470  } else {
2471  shown = true;
2472  }
2473  }
2474  return shown;
2475 }
2476 
2477 
2479 {
2480  return !m_Context->IsOverviewMode() && m_Score && m_Score->HasScores();
2481 }
2482 
2483 
2485 {
2486  // Only for pairwise alignments with a minimal screen size
2488  !m_Context->IsOverviewMode() &&
2489  align_len > kTailGlyphLen &&
2491  (m_Config->m_ShowUnalignedTailsForTrans2GenomicAln && m_SeqAlign->GetSegs().IsSpliced())) &&
2492  x_IsPWAlign();
2493 }
2494 
2496 {
2497  if (e5_Prime == tail)
2498  return TSeqRange(ctx.f - ctx.tail_5*ctx.base_width_curr, ctx.f - 1);
2499  else
2500  return TSeqRange(ctx.t + 1, ctx.t + ctx.tail_3*ctx.base_width_curr);
2501 }
2502 
2504 {
2505  int aligned_seq = m_AlnMgr->GetQuery();
2506  TSignedSeqPos aln_start = m_AlnMgr->GetSeqStart(aligned_seq) / ctx.base_width_curr;
2507  TSignedSeqPos aln_stop = m_AlnMgr->GetSeqStop(aligned_seq) / ctx.base_width_curr;
2508 
2509  if (ctx.reverse_strand) {
2510  if (e5_Prime == tail) {
2511  TSignedSeqPos start = (ctx.f - aln_range.GetToOpen()) / ctx.base_width_curr;
2512  start *= ctx.base_width_anchor;
2513  start += aln_stop + 1;
2514  TSignedSeqPos end = (ctx.f - aln_range.GetFrom()) / ctx.base_width_curr;
2515  end *= ctx.base_width_anchor;
2516  end += aln_stop + 1;
2517  return TSeqRange(start, end);
2518  }
2519  else { // e3_Prime
2520  TSignedSeqPos start = (aln_range.GetToOpen() - ctx.t - 1) / ctx.base_width_curr;
2521  start *= ctx.base_width_anchor;
2522  start = aln_start - start;
2523  TSignedSeqPos end = (aln_range.GetFrom() - ctx.t - 1) / ctx.base_width_curr;
2524  end *= ctx.base_width_anchor;
2525  end = aln_start - end;
2526  return TSeqRange(start, end);
2527  }
2528  }
2529  else {
2530  if (e5_Prime == tail) {
2531  TSignedSeqPos start = (aln_range.GetFrom() - ctx.f) / ctx.base_width_curr;
2532  start *= ctx.base_width_anchor;
2533  start += aln_start;
2534  TSignedSeqPos end = (aln_range.GetToOpen() - ctx.f) / ctx.base_width_curr;
2535  end *= ctx.base_width_anchor;
2536  end += aln_start;
2537  return TSeqRange(start, end);
2538  }
2539  else { // e3_Prime
2540  TSignedSeqPos start = (aln_range.GetFrom() - ctx.t) / ctx.base_width_curr;
2541  start *= ctx.base_width_anchor;
2542  start += aln_stop;
2543  TSignedSeqPos end = (aln_range.GetToOpen() - ctx.t) / ctx.base_width_curr;
2544  end *= ctx.base_width_anchor;
2545  end += aln_stop;
2546  return TSeqRange(start, end);
2547  }
2548  }
2549 }
2550 
2552 {
2553  IRender& gl = GetGl();
2554 
2555  TModelUnit h_text = gl.TextHeight(&m_Config->m_LabelFont);
2556  if (h_text >= GetBarHeight())
2557  return 0.0;
2558 
2559  string len_str = NStr::IntToString(tail, NStr::fWithCommas);
2560  return m_Context->ScreenToSeq(gl.TextWidth(&m_Config->m_LabelFont, len_str.c_str()));
2561 }
2562 
2563 TModelUnit CAlignGlyph::x_GetTailWidth(const TSignedSeqPos tail, const TSignedSeqPos visible_tail, const TSignedSeqPos base_width_curr) const
2564 {
2565  TModelUnit tail_len = 0;
2566  TModelUnit tail_label_len = 0;
2567  TModelUnit bar_h = GetBarHeight();
2568  bool compact = (GetBarHeight() <= 2); // tiny bars, compact mode
2569 
2570  int label_space_pix = compact ? kCompactLabelSpace_h : kLabelSpace_h;
2571  int tail_len_pix = compact ? kCompactTailGlyphLen : kTailGlyphLen;
2572  tail_len_pix += label_space_pix;
2573 
2574  switch (m_Config->m_UnalignedTailsMode) {
2576  // Preserve horizontal space for the unaligned tail glyph
2577  tail_len = m_Context->ScreenToSeq(tail_len_pix);
2578  tail_label_len = x_GetTailLabelWidth(tail);
2579  if (tail_label_len > 0) {
2580  // Preserve horizontal space for the unaligned tail length label
2581  tail_len += tail_label_len + m_Context->ScreenToSeq(label_space_pix);
2582  }
2583  break;
2585  // Preserve space for the unaligned sequence
2586  tail_len = visible_tail*base_width_curr;
2587  if (visible_tail < tail) { // The visible unaligned sequence is truncated
2588  // Preserve horizontal space for the unaligned tail glyph
2589  tail_len += m_Context->ScreenToSeq(tail_len_pix);
2590  tail_label_len = x_GetTailLabelWidth(tail - visible_tail);
2591  if (tail_label_len > 0) {
2592  // Preserve horizontal space for the unaligned tail length label
2593  tail_len += tail_label_len + m_Context->ScreenToSeq(label_space_pix);
2594  }
2595  }
2596  break;
2597  default:
2598  break;
2599  }
2600  return tail_len;
2601 }
2602 
2604 {
2605  try {
2606  int aligned_seq = m_AlnMgr->GetAnchor() == 0 ? 1 : 0;
2608  string id_str = shdl.GetSeqId()->AsFastaString();
2609  return ((id_str.find("gnl|SRA") != string::npos) && (CSeqUtils::IsVDBAccession(m_OrigSeqAlign.GetAnnot().GetName())));
2610  }
2611  catch (const CException&) {
2612 
2613  }
2614  return false;
2615 }
2616 
2617 void CAlignGlyph::x_GetOverrideColor(bool& override_color,
2618  CRgbaColor& read_status_color) const
2619 {
2620  // Special colors for sra reads with errors: failed reads red,
2621  // pcr duplicates pale gray. SV-2153
2622  override_color = false;
2623 
2624  if (m_SeqAlign->IsSetExt()) {
2625  const CSeq_align_Base::TExt& exts = m_SeqAlign->GetExt();
2626  ITERATE (CSeq_align_Base::TExt, iter, exts) {
2627  if ((*iter)->GetType().IsStr() &&
2628  (*iter)->GetType().GetStr() == "PCR duplicate") {
2629  override_color = true;
2630  read_status_color.Set(0.9f, 0.67f, 0.9f, m_FadeFactor);
2631  }
2632  if ((*iter)->GetType().IsStr() &&
2633  (*iter)->GetType().GetStr() == "Poor sequence quality") {
2634  override_color = true;
2635  read_status_color.Set(1.0f, 0.17f, 0.0f, m_FadeFactor);
2636  }
2637  }
2638  }
2639 }
2640 
2641 bool CAlignGlyph::LessBySeqPos(const CSeqGlyph& obj) const
2642 {
2643  const CAlignGlyph* align = dynamic_cast<const CAlignGlyph*>(&obj);
2644  if (align) try {
2645  int anchor1 = align->GetAlignMgr().GetAnchor();
2646  int from1 = align->GetAlignMgr().GetSeqStart(anchor1);
2647 
2648  int anchor0 = m_AlnMgr->GetAnchor();
2649  int from0 = m_AlnMgr->GetSeqStart(anchor0);
2650  if (from0 < from1)
2651  return true;
2652  if (from0 > from1)
2653  return false;
2654  int to1 = align->GetAlignMgr().GetSeqStop(anchor1);
2655  int to0 = m_AlnMgr->GetSeqStop(anchor0);
2656  return to0 < to1;
2657  } catch (CException&) {
2658  }
2659  // otherwise, using default, compare by SeqRanges
2660  return CSeqGlyph::LessBySeqPos(obj);
2661 }
2662 
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
T round(const T &v)
USING_SCOPE(objects)
double CompressLength(double len)
static void FSetPixMaxCoverage(SScPix &dst, const SScPix &src, float fraction, bool)
a pixel with the Max coverage (fraction) overrides all attributes
static const int kCompactLabelSpace_h
static const TSeqPos kTailGlyphLen
static float kMinSegDistance
static const int kLabelSpace_v
static const int kAlignRowSpace
static void FSetPix2(SScPix2 &dst, const SScPix2 &src, float fraction, bool long_seg)
accumulate weighted scores
static const TSeqPos kCompactTailGlyphLen
static const int kLabelSpace_h
static const TModelUnit kPWAlignPackLevel
#define false
Definition: bool.h:36
ELabelPosition m_LabelPos
@ eNormal
no compact mode
@ eExtremeCompact
extreme compact mode
CRgbaColor m_SeqMismatch
CRgbaColor m_TailColor
CGlTextureFont m_LabelFont
CRgbaColor m_Sequence
CRgbaColor m_Insertion
CGlTextureFont m_SeqFont
ECompactMode m_CompactMode
Alignment layout compact mode.
CRgbaColor m_UnalignedSequence
bool m_ShowUnalignedTailsForTrans2GenomicAln
CRgbaColor m_UnalignedFG
CRgbaColor m_NonConsensus
EUnalignedTailsMode m_UnalignedTailsMode
@ ePos_Above
above the rendered bar
@ ePos_Side
always on 5' side
@ ePos_NoLabel
no label
CBioseq_Handle –.
void SetId(int)
CGlAttrGuard - guard class for restoring OpenGL attributes.
Definition: glutils.hpp:130
@ fNoCaching
The tooltip for this feature should not be cached.
int m_Flags
area flags, will need to replace m_Type
bool m_PositiveStrand
the default is true
static string GetAlignSignature(const objects::CSeq_align &align, const objects::CSeq_loc &on_loc, objects::CScope *scope, const objects::CSeq_annot_Handle &annot_handle)
bool IsHorizontal() const
void TextOut(const CGlTextureFont *font, const char *text, TModelUnit x, TModelUnit y, bool center, bool adjust_flip=true) const
void DrawTriangle(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2, TModelUnit x3, TModelUnit y3, bool border=false) const
CGlPane * GetGlPane()
inline method implementations
TModelRange IntersectVisible(const CSeqGlyph *obj) const
TVPUnit SeqToScreenX(const TModelUnit &size) const
void DrawLineStrip(const vector< TModelPoint > &points) const
void DrawUnalignedTail(TModelUnit x1, TModelUnit x2, TModelUnit y1, TModelUnit y2, bool is_polya, const CRgbaColor &color) const
void DrawLine(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2) const
void DrawStippledLine(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2, int factor=2, unsigned short pattern=0xAAAA) const
objects::CScope & GetScope()
void DrawQuad(const TModelRect &rc, bool border=false) const
const TModelUnit & GetScale() const
void DrawSelection(const TModelRect &rc) const
TModelUnit SeqToScreen(const TModelUnit &size) const
convert from sequence positions to screen pixels
TModelUnit SeqToScreenXInModelUnit(const TModelUnit &size) const
TModelUnit ScreenToSeq(const TModelUnit &size) const
convert from screen pixels to sequence positions
bool IsOverviewMode() const
bool IsFlippedStrand() const
bool WillSeqLetterFit() const
is it enougth space to sequence letters.
void DrawDisk2(const TModelPoint &p, TModelUnit size, CRgbaColor color)
const CRgbaColor & GetSelLabelColor() const
void DrawLine_NoAA(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2) const
TSeqPos GetViewWidth() const
bool WillLabelFit(const TModelRect &rc) const
void Draw3DQuad(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2, const CRgbaColor &color, bool border=false) const
void DrawBackground(const TModelRect &rcm, TModelUnit border) const
void DrawGreaterLessSign(TModelUnit x1, TModelUnit x2, TModelUnit bar_h, bool negative) const
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
CScope –.
Definition: scope.hpp:92
class CSeqGlyph defines an interface that wraps a rectilinear abstract object.
Definition: seq_glyph.hpp:82
void x_InitHTMLActiveArea(CHTMLActiveArea &area) const
initialize the basic information for a given active area.
Definition: seq_glyph.cpp:380
CRenderingContext * m_Context
the rendering context
Definition: seq_glyph.hpp:346
virtual void SetHeight(TModelUnit h)
Definition: seq_glyph.hpp:650
virtual TModelUnit GetRight() const
Definition: seq_glyph.hpp:603
virtual void SetWidth(TModelUnit w)
Definition: seq_glyph.hpp:646
bool IsSelected() const
Definition: seq_glyph.hpp:573
virtual void SetLeft(TModelUnit l)
Definition: seq_glyph.hpp:654
virtual TModelUnit GetTop() const
Definition: seq_glyph.hpp:599
virtual TModelUnit GetHeight() const
Definition: seq_glyph.hpp:587
virtual bool LessBySeqPos(const CSeqGlyph &obj) const
compare this object to another based on glyph sequence position.
Definition: seq_glyph.hpp:534
float GetFadeFactor() const
Definition: seq_glyph.hpp:742
size_t GetTearline() const
Definition: seq_glyph.hpp:736
size_t GetVisible() const
Definition: seq_glyph.hpp:284
virtual TModelUnit GetWidth() const
Definition: seq_glyph.hpp:591
virtual TModelUnit GetLeft() const
Definition: seq_glyph.hpp:595
TModelRect GetModelRect() const
get the bounding box.
Definition: seq_glyph.hpp:562
vector< CHTMLActiveArea > TAreaVector
Definition: seq_glyph.hpp:84
virtual TModelUnit GetBottom() const
Definition: seq_glyph.hpp:607
static SIZE_TYPE Reverse(const string &src, TCoding src_coding, TSeqPos pos, TSeqPos length, string &dst)
static SIZE_TYPE ReverseComplement(const string &src, TCoding src_coding, TSeqPos pos, TSeqPos length, string &dst)
static SIZE_TYPE Complement(const string &src, TCoding src_coding, TSeqPos pos, TSeqPos length, string &dst)
@ e_Iupacna
Definition: sequtil.hpp:47
@ e_Iupacaa
Definition: sequtil.hpp:55
CSeqVector –.
Definition: seq_vector.hpp:65
@ eScore_IdentityCount
Definition: Seq_align.hpp:145
@ eScore_PercentIdentity
Definition: Seq_align.hpp:189
ENa_strand GetSeqStrand(TDim row) const
Get strand (the first one if segments have different strands).
Definition: Spliced_seg.cpp:56
@ eRight
Towards higher aln coord (always to the right)
@ eLeft
Towards lower aln coord (always to the left)
@ eBackwards
Towards lower seq coord (to the left if plus strand, right if minus)
@ eForward
Towards higher seq coord (to the right if plus strand, left if minus)
virtual EPolyATail HasPolyATail() const =0
Check if there is any unaligned polyA tail.
pair< ECigarOp, size_t > TCigarPair
virtual void GetUnalignedTails(TSignedSeqPos &start_tail, TSignedSeqPos &end_tail, bool clipped=true) const
virtual const TCigarPair * GetCigarAtAlnPos(int row, TSignedSeqPos pos) const
virtual bool IsRegular() const
virtual bool IsNegativeStrand(TNumrow row) const =0
virtual const objects::CBioseq_Handle & GetBioseqHandle(IAlnExplorer::TNumrow row) const =0
virtual TSeqRange GetAlnRangeWithTails() const
IAlnExplorer::TNumrow TNumrow
virtual TSeqPos GetSeqStart(TNumrow row) const =0
virtual const objects::CSeq_id & GetSeqId(TNumrow row) const =0
int GetGenCode(IAlnExplorer::TNumrow row) const
virtual TSignedRange GetSeqAlnRange(TNumrow row) const =0
virtual IAlnExplorer::TNumrow GetQuery() const
virtual TSeqPos GetSeqStop(TNumrow row) const =0
virtual TSignedSeqPos GetAlnPosFromSeqPos(TNumrow row, TSeqPos seq_pos, IAlnExplorer::ESearchDirection dir=IAlnExplorer::eNone, bool try_reverse_dir=true) const =0
virtual TSeqPos GetFrom() const =0
virtual float GetAttr() const =0
virtual TSeqPos GetTo() const =0
Alignment segment iterator interface.
@ eAllSegments
Iterate all segments.
@ eSkipGaps
Skip gap segments (show only aligned ranges)
Alignment segment interface.
virtual const TSignedRange & GetRange(void) const =0
Get the selected row range.
@ fAligned
Aligned segment.
@ fIndel
Either anchor or the selected row is not present in the segment.
@ fUnaligned
The range on the selected sequence does not participate in the alignment (the alignment range of the ...
virtual TSegTypeFlags GetType(void) const =0
Get current segment type.
bool IsIndel(void) const
bool IsAligned(void) const
bool IsGap(void) const
Check if there's a gap on the selected row.
virtual const TSignedRange & GetAlnRange(void) const =0
Get alignment range for the segment.
vector< TSeqRange > TIntervals
virtual TSeqPos GetBaseWidth(IAlnExplorer::TNumrow) const =0
virtual string & GetAlnSeqString(IAlnExplorer::TNumrow row, string &buffer, const IAlnExplorer::TSignedRange &aln_range) const =0
virtual IAlnExplorer::TNumrow GetNumRows() const =0
virtual IAlnExplorer::TNumrow GetAnchor() const =0
virtual IAlnSegmentIterator * CreateSegmentIterator(IAlnExplorer::TNumrow, const IAlnExplorer::TSignedRange &, IAlnSegmentIterator::EFlags) const =0
virtual TSignedSeqPos GetSeqPosFromAlnPos(IAlnExplorer::TNumrow for_row, TSeqPos aln_pos, IAlnExplorer::ESearchDirection dir=IAlnExplorer::eNone, bool try_reverse_dir=true) const =0
primitive interface to arrange tabular data in the tooltips
Definition: tooltip.hpp:55
bool IsConsensusSplice(const string &splice5, const string &splice3)
Consensus splice is GY..AG or AT..AC.
Include a standard set of the NCBI C++ Toolkit most basic headers.
CS_CONTEXT * ctx
Definition: t0006.c:12
unsigned int TSeqPos
Type for sequence locations and lengths.
Definition: ncbimisc.hpp:875
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
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 LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
bool IsSimplified() const
void x_DrawInserts(const SDrawContext &ctx) const
virtual void x_Draw() const
The default renderer for this layout object.
bool x_IsSRA() const
virtual bool NeedTooltip(const TModelPoint &p, ITooltipFormatter &tt, string &t_title) const
Check if need to show tooltip.
void x_CalcIntervals(TIntervals &intervals, int target_row=-1) const
void x_DrawStrandIndicators(const SDrawContext &ctx) const
virtual void GetHTMLActiveAreas(TAreaVector *p_areas) const
Get html active areas.
virtual bool HasObject(CConstRef< CObject > obj) const
check if the wrapped object(s) is the one.
virtual bool LessBySeqPos(const CSeqGlyph &obj) const
compare this object to another based on glyph sequence position.
vector< TModelRange > TMUnitRanges
void x_RenderAveragableScores(TModelUnit yy, TSignedSeqRange aln_range, TSeqRange seq_range, TModelUnit height, int row, bool override_color, const CRgbaColor &read_status_color) const
void x_DrawMultiAlignLabel(int row, TModelUnit y) const
void x_DrawUnalignedBar(const ETail tail, const SDrawContext &ctx, const CRgbaColor &c_fg) const
CAlignGlyph(CConstRef< IAlnGraphicDataSource > aln_mgr, const objects::CSeq_align_Handle &orig_align, const objects::CSeq_align &mapped_align, int orig_anchor)
virtual CConstRef< CObject > GetObject(TSeqPos pos) const
access our core component - we wrap an object(s) of some sort.
TSeqRange x_ConvertAlnTaillRngToSeqRng(const ETail tail, const SDrawContext &ctx, const TSeqRange &aln_range) const
virtual void GetObjects(vector< CConstRef< CObject > > &objs) const
retrieve CObjects corresponding to this CSeqGlyph.
void x_DrawMultiAlign() const
void x_GetOverrideColor(bool &override_color, CRgbaColor &read_status_color) const
TModelUnit x_GetTailLabelWidth(const TSignedSeqPos tail) const
TIntervals m_Intervals
intervals.
virtual string GetSignature() const
return signature for this glyph.
void GetTitle(string *title, CLabel::ELabelType type) const
bool x_ShowLabel() const
void x_DrawNonConsensusSpliceSites(const SDrawContext &ctx) const
void x_RenderNonAveragableScores(TModelUnit yy, TSignedSeqRange aln_range, TSeqRange seq_range, TModelUnit height, int row, bool override_color, const CRgbaColor &read_status_color) const
void x_DrawNoScoreAlign(const SDrawContext &ctx, const CRgbaColor &c_fg) const
void DrawPWAlignElem(const TModelRect &rcm, bool selected, bool show_label, const CRgbaColor &c_fg, const CRgbaColor &c_seq, const CRgbaColor &c_mis) const
virtual TSeqRange GetRange(void) const
get the total range of this object.
const IAlnGraphicDataSource & GetAlignMgr(void) const
Inline methods.
void x_DrawIntronsAndInternalUnalignedRegions(const SDrawContext &ctx, TSignedSeqPos from, TSignedSeqPos to) const
void x_DrawGaps(const SDrawContext &ctx) const
virtual void GetTooltip(const TModelPoint &p, ITooltipFormatter &tt, string &t_title) const
Get the tooltip if available.
CConstRef< CAlignmentConfig > m_Config
const objects::CSeq_align_Handle & GetOrigAlignment(void) const
void ApplyFading() const
virtual bool IsClickable() const
Query if this glyph is clickable.
bool x_ShowScore() const
void x_DrawUnalignedRowSequence(const ETail tail, const SDrawContext &ctx, const CRgbaColor &c_fg) const
virtual const objects::CSeq_loc & GetLocation(void) const
access the position of this object.
void x_DrawInternalUnalignedRegions(const SDrawContext &ctx, TMUnitRanges &unaligned_regions) const
CRef< objects::CSeq_loc > m_Location
static bool IsVDBAccession(const string &acc)
Check if string starts with ("SRA", "SRR", "DRR", "ERR")
Definition: utils.cpp:887
TModelUnit GetBarHeight() const
TModelUnit x_GetTailWidth(const TSignedSeqPos tail, const TSignedSeqPos visible_tail, const TSignedSeqPos base_width_curr) const
virtual const TIntervals & GetIntervals(void) const
access sub-intervals (if any).
bool IsLastRow() const
void x_DrawAlignRowSequence(TModelUnit center_y, int row, const CRgbaColor &c_fg, const CRgbaColor &c_seq, const CRgbaColor &c_mis) const
TSeqRange x_GetAlnTailRange(const ETail tail, const SDrawContext &ctx) const
void x_DrawSimplified(const SDrawContext &ctx, const CRgbaColor &c_fg) const
virtual void x_UpdateBoundingBox()
Update the bounding box assuming children's sizes are fixed if any.
CConstRef< IAlnGraphicDataSource > m_AlnMgr
pointer to the actual alignment information.
bool x_ShowUnalignedTails(TModelUnit align_len) const
bool m_DisableTooltipsCaching
Indicates whether the front-end can cache the tooltips.
bool x_IsPWAlign() const
void x_DrawTailSequences(const SDrawContext &ctx, const CRgbaColor &c_fg) const
void x_DrawPWAlign() const
const objects::CSeq_align & GetAlignment(void) const
CConstRef< objects::CSeq_align > m_SeqAlign
CConstIRef< ISGAlnScore > m_Score
objects::CSeq_align_Handle m_OrigSeqAlign
int m_OrigAnchor
The anchor row number in original Seq-algin, not alnmgr.
void x_DrawTailGlyphs(const SDrawContext &ctx, bool show_label, const CRgbaColor &c_fg) const
@ eMaxRowLimit
GLdouble TModelUnit
Definition: gltypes.hpp:48
virtual void Scalef(GLfloat x, GLfloat y, GLfloat z)=0
T X() const
Definition: glpoint.hpp:59
virtual void Enable(GLenum glstate)=0
virtual void Begin(GLenum mode)=0
Start rendering.
T Top() const
Definition: glrect.hpp:84
virtual void BlendFunc(GLenum sfactor, GLenum dfactor)=0
Options to be used when GL_BLEND is enabled.
void Color3f(GLfloat r, GLfloat g, GLfloat b)
Definition: irender.hpp:95
T Bottom() const
Definition: glrect.hpp:82
T Width() const
Definition: glrect.hpp:86
IRender & GetGl()
convenience function for getting current render manager
void Vertex2d(GLdouble x, GLdouble y)
Definition: irender.hpp:185
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
virtual TModelUnit TextHeight(const CGlTextureFont *font) const =0
virtual TModelUnit TextWidth(const CGlTextureFont *font, const char *text) const =0
void Color4d(GLdouble r, GLdouble g, GLdouble b, GLdouble a)
Definition: irender.hpp:102
virtual void PopMatrix()=0
virtual void End()=0
Finish rendering (create buffer and send to renderer)
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
int TVPUnit
Definition: gltypes.hpp:47
void Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
Definition: irender.hpp:97
TModelRect & GetVisibleRect(void)
Definition: glpane.hpp:357
CGlRect< TModelUnit > TModelRect
Definition: gltypes.hpp:54
virtual void Disable(GLenum glstate)=0
glDisable()
virtual void LineWidth(GLfloat w)=0
Set line width for drawing: glLineWidth()
TModelUnit GetScaleY(void) const
Definition: glpane.cpp:123
CGlPoint< TModelUnit > TModelPoint
Definition: gltypes.hpp:51
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
virtual void PushMatrix()=0
string Truncate(const char *text, TModelUnit w, ETruncate trunc=eTruncate_Ellipsis) const
Truncate text to the secified width.
void SetDataSource(const CConstRef< IAlnGraphicDataSource > &data_source)
static void GetLabel(const CObject &obj, string *label, ELabelType type=eDefault)
Definition: label.cpp:140
void SetFlippedStrands(bool flipped=true)
virtual void AddRow(const string &sContents="", unsigned colspan=2)=0
add a row with a cell, spanning across all columns
void Set(float r, float g, float b)
set the color from an Fl_Color
Definition: rgba_color.cpp:226
float GetBlue(void) const
Definition: rgba_color.hpp:333
float GetGreen(void) const
Definition: rgba_color.hpp:327
void SetAlpha(float r)
Definition: rgba_color.cpp:287
void Lighten(float scale)
Definition: rgba_color.cpp:463
static CRgbaColor Interpolate(const CRgbaColor &color1, const CRgbaColor &color2, float alpha)
Interpolate two colors.
Definition: rgba_color.cpp:444
static bool IsPolyA(const objects::CBioseq_Handle &bsh, TSeqPos start, TSeqPos stop)
ELabelType
Definition: label.hpp:60
float GetRed(void) const
Get specific channels in floating point values.
Definition: rgba_color.hpp:321
@ eType
Definition: label.hpp:65
@ eDefault
Definition: label.hpp:73
@ eUserTypeAndContent
Definition: label.hpp:66
@ eContent
Definition: label.hpp:62
@ eDescription
Definition: label.hpp:68
@ eDescriptionBrief
Definition: label.hpp:67
const string AsFastaString(void) const
Definition: Seq_id.cpp:2265
CConstRef< CSeq_id > GetSeqId(void) const
virtual void Assign(const CSerialObject &source, ESerialRecursionMode how=eRecursive)
Override Assign() to incorporate cache invalidation.
Definition: Seq_loc.cpp:337
void SetId(CSeq_id &id)
set the 'id' field in all parts of this location
Definition: Seq_loc.cpp:3474
const CSeq_id & GetId(const CSeq_loc &loc, CScope *scope)
If all CSeq_ids embedded in CSeq_loc refer to the same CBioseq, returns the first CSeq_id found,...
TSeqPos GetLength(const CSeq_id &id, CScope *scope)
Get sequence length if scope not null, else return max possible TSeqPos.
static void Translate(const string &seq, string &prot, const CGenetic_code *code, bool include_stop=true, bool remove_trailing_X=false, bool *alt_start=NULL, bool is_5prime_complete=true, bool is_3prime_complete=true)
Translate a string using a specified genetic code.
Definition: sequence.cpp:4095
@ fIs5PrimePartial
= 0x4 Translate first codon even if not start codon (because sequence is 5' partial)
Definition: sequence.hpp:984
@ eGetId_Canonical
Definition: sequence.hpp:114
TSeqPos GetBioseqLength(void) const
bool IsAa(void) const
CSeqVector GetSeqVector(EVectorCoding coding, ENa_strand strand=eNa_strand_plus) const
Get sequence: Iupacna or Iupacaa if use_iupac_coding is true.
@ eCoding_Iupac
Set coding to printable coding (Iupacna or Iupacaa)
void GetSeqData(TSeqPos start, TSeqPos stop, string &buffer) const
Fill the buffer string with the sequence data for the interval [start, stop).
Definition: seq_vector.cpp:304
TObjectType * GetPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1684
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
position_type GetLength(void) const
Definition: range.hpp:158
TThisType IntersectionWith(const TThisType &r) const
Definition: range.hpp:312
position_type GetToOpen(void) const
Definition: range.hpp:138
TThisType & Set(position_type from, position_type to)
Definition: range.hpp:188
bool Empty(void) const
Definition: range.hpp:148
CRange< TSeqPos > TSeqRange
typedefs for sequence ranges
Definition: range.hpp:419
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
#define kEmptyStr
Definition: ncbistr.hpp:123
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5083
static string UIntToString(unsigned int value, TNumToStringFlags flags=0, int base=10)
Convert UInt to string.
Definition: ncbistr.hpp:5108
@ fWithCommas
Use commas as thousands separator.
Definition: ncbistr.hpp:254
static const char label[]
void SetFrom(TFrom value)
Assign a value to From data member.
Definition: Range_.hpp:231
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
void SetTo(TTo value)
Assign a value to To data member.
Definition: Range_.hpp:278
const TDonor_after_exon & GetDonor_after_exon(void) const
Get the Donor_after_exon member data.
TGenomic_start GetGenomic_start(void) const
Get the Genomic_start member data.
const TAcceptor_before_exon & GetAcceptor_before_exon(void) const
Get the Acceptor_before_exon member data.
bool IsSetAcceptor_before_exon(void) const
splice sites Check if a value has been assigned to Acceptor_before_exon data member.
list< CRef< CUser_object > > TExt
Definition: Seq_align_.hpp:402
list< CRef< CSpliced_exon > > TExons
const TExons & GetExons(void) const
Get the Exons member data.
const TBases & GetBases(void) const
Get the Bases member data.
TGenomic_end GetGenomic_end(void) const
Get the Genomic_end member data.
bool IsSetDonor_after_exon(void) const
Check if a value has been assigned to Donor_after_exon data member.
@ eNa_strand_plus
Definition: Na_strand_.hpp:66
@ eNa_strand_minus
Definition: Na_strand_.hpp:67
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
n background color
int i
int len
range(_Ty, _Ty) -> range< _Ty >
constexpr auto sort(_Init &&init)
const struct ncbi::grid::netcache::search::fields::SIZE size
#define abs(a)
Definition: ncbi_heapmgr.c:130
unsigned int a
Definition: ncbi_localip.c:102
T max(T x_, T y_)
T log10(T x_)
T min(T x_, T y_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
static int match(register const pcre_uchar *eptr, register const pcre_uchar *ecode, const pcre_uchar *mstart, int offset_top, match_data *md, eptrblock *eptrb, unsigned int rdepth)
Definition: pcre_exec.c:513
represents a pixel with two scores, one corresponds to a gap interval, another - to an aligned segmen...
Definition: align_row.cpp:1708
float m_MinScore
Definition: align_row.cpp:1713
float m_IntScore
Definition: align_row.cpp:1709
bool operator==(const SScPix2 &other) const
bool m_Init
Definition: align_row.cpp:1714
float m_IntLen
Definition: align_row.cpp:1710
float m_GapScore
Definition: align_row.cpp:1711
float m_GapLen
Definition: align_row.cpp:1712
represents a pixel with a score, if several intervals cover a pixel, the interval with the maximum co...
Definition: align_row.cpp:1637
float m_MaxCoverage
score assigned to the pixel
Definition: align_row.cpp:1639
bool m_Gap
fraction of the pixel corresponding to the m_Score
Definition: align_row.cpp:1640
float m_Score
Definition: align_row.cpp:1638
bool operator==(const SScPix &other) const
true if this is a gap interval
Definition: type.c:6
Modified on Fri Dec 01 04:49:07 2023 by modify_doxy.py rev. 669887