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

Go to the SVN repository for this file.

1 /* $Id: histogram_glyph.cpp 47464 2023-04-20 00:19:10Z evgeniev $
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, Andrei Shkeda
27 *
28 * File Description:
29 * CHistogramGlyph -- utility class for having
30 * feature density histograms his in graphical layouts.
31 *
32 */
33 
34 #include <ncbi_pch.hpp>
37 #include <gui/objutils/tooltip.hpp>
39 #include <gui/objutils/utils.hpp>
40 #include <gui/opengl/irender.hpp>
41 #include <gui/opengl/glutils.hpp>
45 #include <gui/utils/splines/Splines.hh>
46 
47 #include <gui/opengl/glpoint.hpp>
54 
57 
58 #ifdef ATTRIB_MENU_SUPPORT
59  int CHistogramGlyph::m_SDMult = 5;
60  float CHistogramGlyph::m_SD = 0.0f;
61 #endif
62 
63 #define M_NCBI_E 2.71828182845904523536
64 static const float kDataPointRadius = 3.;
65 
66 static const int kRulerLebelsMinDistance = 200;
67 
68 static const int kLegendBarWidth = 30;
69 static const int kLegendLabelGap = 5;
70 static const int kLegenPadding = 5;
71 
72 static const string kCoverageLabel = "Coverage";
73 
74 
75 
76 CHistogramData::CHistogramData(TSeqPos start, TSeqPos stop, double window, accum_functor* funct, float def)
77  : CDensityMap<float>(start, stop, window, funct, def)
78  , m_InterpolationMethod(eInterpolation_None)
79 {
80 }
81 
82 
84  : CDensityMap<float>(map)
85  , m_DataPoints(map.m_DataPoints)
86  , m_InterpolationMethod(map.m_InterpolationMethod)
87  , m_FirstPoint(map.m_FirstPoint)
88  , m_LastPoint(map.m_LastPoint)
89 {
90 }
91 
93 {
94  // check self assignment
95  if (this == &map)
96  return *this;
98  m_DataPoints = map.m_DataPoints;
99  m_InterpolationMethod = map.m_InterpolationMethod;
100  m_FirstPoint = map.m_FirstPoint;
101  m_LastPoint = map.m_LastPoint;
102  return *this;
103 }
104 
105 void CHistogramData::InitDataPoints(const TModelPoint& first_point, const TModelPoint& last_point)
106 {
107  m_FirstPoint = first_point;
108  m_LastPoint = last_point;
109  double min_v = GetMin();
110  double max_v = GetMax();
111  min_v = min(min_v, min(m_FirstPoint.Y(), m_LastPoint.Y()));
112  max_v = max(max_v, max(m_FirstPoint.Y(), m_LastPoint.Y()));
113  double last_val = 0;
114  int last_x = -1;
115 
116  for (int x = 0; x < GetBins(); ++x) {
117  if ((*this)[x] != GetDefVal()) {
118  if (last_x == -1) {
119  last_x = x;
120  last_val = (*this)[x];
121  } else if (last_val != (*this)[x]) {
122  last_x += (x - last_x) / 2;
123  m_DataPoints.push_back(last_x);
124  last_val = (*this)[x];
125  last_val < min_v ? min_v = last_val : max_v = max(max_v, last_val);
126  last_x = -1;
127  }
128  } else if (last_x != -1) {
129  last_x += (x - last_x) / 2;
130  m_DataPoints.push_back(last_x);
131  last_val < min_v ? min_v = last_val : max_v = max(max_v, last_val);
132  last_x = -1;
133  }
134  }
135  if (last_x != -1) {
136  last_x += (GetBins() - last_x) / 2;
137  m_DataPoints.push_back(last_x);
138  last_val < min_v ? min_v = last_val : max_v = max(max_v, last_val);
139  }
140  SetMin(min_v);
141  SetMax(max_v);
142  if (GetMax() == GetMin()) {
143  (GetMax() > 0) ? SetMin(0) : SetMax(0);
144  }
145 }
146 
148 {
149  return ctx.GetScale() <= 1.0f/2.0f;
150 }
151 
152 
154 {
157  double m_AxisMax;
158  double m_AxisMin;
159  int m_Height;
161  SLogScaleData(double AxisMax, double AxisMin, int height, CHistParams::EScale scale)
163  , m_AxisMax(AxisMax), m_AxisMin(AxisMin), m_Height(height), m_Scale(scale)
164  {
166  return;
169  }
170 
171  void x_InitDenominator(double AxisMax, double& denom)
172  {
173  double tick_n = 0;
174  double log_remainder = 0;
175  if (AxisMax <= 0)
176  return;
177  double log_max = 0;
178  if (AxisMax > FLT_EPSILON) {
180  log_max = log10((double)AxisMax);
181  else if (m_Scale == CHistParams::eLog2)
182  log_max = log((double)AxisMax) / log(2.0); //log2 not supported on windows
183  else
184  log_max = log((double)AxisMax);
185  }
186  log_remainder = log_max - floor(log_max);
187  log_max = floor(log_max);
188  tick_n = (int)log_max;
189  if (tick_n == 0) { // if AxisMax is <= 1
190  tick_n = 1;
191  log_remainder = 0.0;
192  }
193  denom = tick_n + log_remainder;
194  }
195 
196  // If the desired display format is log, convert value to log
197 
198  double MapValue(double val)
199  {
200  if (m_Scale == CHistParams::eLinear) {
201  return val;
202  }
203 
204  int dir = val > 0 ? 1 : -1;
205  TModelUnit y_ratio = (m_AxisMin < 0 && m_AxisMax > 0) ? 0.5f : 1.0;
206  TModelUnit height = y_ratio * m_Height;
207  if (dir < 0 && y_ratio != 1.)
208  height = m_Height - height;
209  val = fabs(val);
210  // Interpolate position based on log scale markings. Values below 1 are linear since
211  // log(0) is undefined and log(0+)..log(0.99.) are negative.
212  // We somewhat arbitrarily place the value 1 at 0.3*(the distance between ticks)
213  //TModelUnit dist_y = GetHeight() / (TModelUnit(tick_n) + log_remainder);
214  TModelUnit dist_denom = dir > 0 ? top_denominator : bottom_denominator;
215  if (dist_denom == 0)
216  dist_denom = 1.0;
217  TModelUnit dist_y = height / dist_denom;
218  if (fabs(val) <= TModelUnit(1.0)) {
219  val = val * 0.3 * dist_y;
220  } else {
221  TModelUnit log_val;
223  log_val = log10(val);
224  else if (m_Scale == CHistParams::eLog2)
225  log_val = log(val) / log(2.0); //log2 not supported on windows
226  else // log e
227  log_val = log(val);
228 
229  // interpolate between the lower and upper tick for this value
230  TModelUnit lower_tick_log = floor(log_val);
231  TModelUnit dist_between_ticks = log_val - lower_tick_log;
232 
233  // Special case for values between 1 and log base since we use 0 as a tick mark rather than 1 (since
234  // this graph does not show values between 0 and 1). Probably a proper graph would have evenly spaced
235  // 0, 1, log_base^1, log_base^2 etc. But here we combine 0-log-base^1 into one tick mark since data
236  // from 0..1 isn't very interesting since this is used with integers (no fractional numbers).
237  if (lower_tick_log == TModelUnit(0))
238  val = TModelUnit(0.3) * dist_y + dist_between_ticks * (dist_y - TModelUnit(0.3) * dist_y);
239  else
240  val = lower_tick_log * dist_y + dist_between_ticks * dist_y;
241  }
242  if (dir < 0)
243  val = -val;
244  return val;
245  }
246 };
247 
248 
249 
250 
251 //
252 // CHistogramGlyph::CHistogramGlyph()
253 //
255  CSeqFeatData::ESubtype subtype, const string& title)
256  : m_DlgHost(NULL)
257  , m_FixedScale(false)
258  , m_AnnotName(CSeqUtils::GetUnnamedAnnot())
259  , m_Subtype(subtype)
260  , m_ShowTitle(false)
261  , m_Mode(eMode_Single)
262 {
263  if(CSeqUtils::isRmtAnnotName(title)) {
264  m_RmtAnnotName = title;
265  }
266  string desc = title;
267  if (desc.empty()) {
268  const CFeatList& feat_list = *CSeqFeatData::GetFeatList();
269  desc = feat_list.GetDescription(
270  CSeqFeatData::GetTypeFromSubtype(subtype), subtype);
271  }
272  m_Maps.insert(TMaps::value_type(desc, map));
273  SetAxisRange();
274 }
275 
276 
277 CHistogramGlyph::CHistogramGlyph(const TMap& map, const string& title)
278  : m_DlgHost(NULL)
279  , m_FixedScale(false)
280  , m_AnnotName(CSeqUtils::GetUnnamedAnnot())
281  , m_Subtype(CSeqFeatData::eSubtype_any)
282  , m_ShowTitle(false)
283  , m_Mode(eMode_Single)
284 {
285  if(CSeqUtils::isRmtAnnotName(title)) {
286  m_RmtAnnotName = title;
287  }
289  SetAxisRange();
290 }
291 
292 
293 CHistogramGlyph::CHistogramGlyph(const TMaps& maps,
294  CSeqFeatData::ESubtype subtype)
295  : m_DlgHost(NULL)
296  , m_FixedScale(false)
297  , m_AnnotName(CSeqUtils::GetUnnamedAnnot())
298  , m_Subtype(subtype)
299  , m_ShowTitle(false)
300  , m_Mode(eMode_Single)
301 {
302  m_Maps = maps;
303  SetAxisRange();
304 }
305 
306 
307 CHistogramGlyph::CHistogramGlyph(const TMaps& maps, const string& name)
308  : m_DlgHost(NULL)
309  , m_FixedScale(false)
310  , m_Subtype(CSeqFeatData::eSubtype_any)
311  , m_ShowTitle(false)
312  , m_Mode(eMode_Single)
313 {
314  SetAnnotName(name);
315  m_Maps = maps;
316  SetAxisRange();
317 }
318 
320 {
321  CRef<CHistParams> params = GetHistParams();
322  //if (params)
323  //params->m_NumBins = 4;
324  bool has_bins = params && (params->m_Type == CHistParams::eSmearBar || params->m_Type == CHistParams::eMergedBar) && params->m_NumBins > 0;
325  if (has_bins)
326  m_FixedScale = true;
327 
330  if (m_AxisMin == m_AxisMax)
331  (m_AxisMax > 0) ? m_AxisMin = 0 : m_AxisMax = 0;
332 
333  if (params.IsNull())
334  return;
335  if (has_bins) {
336  m_NumBins = params->m_NumBins;
337  float max_val = (m_AxisMax - m_AxisMin) + 1;
338  float denom = pow(10, floor(log10(max_val)));
339  max_val = round(max_val/denom) * denom;
340  denom /= 100;
341  m_BinSize = floor(max_val / m_NumBins);
342  m_BinSize = round((float(m_BinSize)/denom)) * denom;
343  }
344 
345 
346  // If we are clipping outliers, compute the standard deviation then set the
347  // maximum possible value to:
348  // mean + (max. standard deviation)*standard-deviation-multiplier OR the current
349  // max value, whichever is lower.
350  if (params->m_ClipOutliers) {
351  TDataType mean;
352  TDataType sdev_max = TDataType(0);
353 
354  ITERATE (TMaps, map_iter, m_Maps) {
355  TDataType standard_deviation = x_ComputeDeviation(map_iter->second, mean);
356  sdev_max = std::max(TDataType(mean + params->m_SDeviationThreshold*standard_deviation), sdev_max);
357  }
358 
359  // If the standard deviation threshold is below the current maximum value,
360  // set the new max value to the highest value below any value in the current
361  // data set that is getting clipped (so outliers are clipped down to the
362  // next lower non-outlier value)
363  if (sdev_max < m_AxisMax) {
364  m_AxisMax = sdev_max;
365  TDataType lowest_max = TDataType(0);
366  ITERATE (TMaps, map_iter, m_Maps) {
367  TDataType low_max = x_HighestValueBelowMax(map_iter->second);
368  lowest_max = std::max(low_max, lowest_max);
369  }
370  if (lowest_max > 0)
371  m_AxisMax = std::min(m_AxisMax, lowest_max);
372  }
373  if (m_AxisMin < 0 && sdev_max < fabs(m_AxisMin)) {
374  m_AxisMin = -sdev_max;
375  TDataType lowest_min = TDataType(0);
376  ITERATE (TMaps, map_iter, m_Maps) {
377  TDataType low_min = x_LowesetValueBelowMin(map_iter->second);
378  lowest_min = std::min(low_min, lowest_min);
379  }
380  m_AxisMin = std::max(m_AxisMin, lowest_min);
381  }
382  }
383  if (params->m_Scale == CHistParams::eLinear && params->m_RangeAutoscale == false) {
384  if (params->m_ValueRange.GetFrom() != params->m_ValueRange.GetEmptyFrom()) {
385  m_AxisMin = params->m_ValueRange.GetFrom();
386  params->m_ClipOutliers = true;
387  }
388  if (params->m_ValueRange.GetTo() != params->m_ValueRange.GetEmptyTo()) {
389  m_AxisMax = params->m_ValueRange.GetTo();
390  params->m_ClipOutliers = true;
391  }
392  }
393 
394  if (!m_FixedScale) {
395  double sign_max = m_AxisMax >= 0 ? 1.0f : -1.0f;
396  double sign_min = m_AxisMin >= 0 ? 1.0f : -1.0f;
397 
398  // Convert axis_max/min to linear based on underlying scale:
399  if (params->m_StoredScale == CHistParams::eLog10) {
400  m_AxisMax = pow(10.0, (double)fabs(m_AxisMax)) * sign_max;
401  m_AxisMin = pow(10.0, (double)fabs(m_AxisMin)) * sign_min;
402  }
403  else if (params->m_StoredScale == CHistParams::eLoge) {
404  m_AxisMax = pow(M_NCBI_E, (double)fabs(m_AxisMax)) * sign_max;
405  m_AxisMin = pow(M_NCBI_E, (double)fabs(m_AxisMin)) * sign_min;
406  }
407  else if (params->m_StoredScale == CHistParams::eLog2) {
408  m_AxisMax = pow(2.0, (double)fabs(m_AxisMax)) * sign_max;
409  m_AxisMin = pow(2.0, (double)fabs(m_AxisMin)) * sign_min;
410  }
411  }
412 // m_AxisMin = floor(m_AxisMin);
413 // m_AxisMax = ceil(m_AxisMax);
414  if (params->m_ClipOutliers == false && m_AxisMin > 0) {
415  m_AxisMin = 0;
416  }
417 
418 
419 #ifdef ATTRIB_MENU_SUPPORT
420  m_SDMult = params->m_SDeviationThreshold;
421 
423  if (!m.FindMenu("Graph Glyph")) {
424  CAttribMenu* sub_menu = m.AddSubMenu("Graph Glyph");
425  sub_menu->AddInt("SD Multiplier", &m_SDMult, 3.0f, 1, 40, 1);
426  sub_menu->AddFloatReadOnly("Standard Deviation: ", &m_SD);
427  }
428 
429 #endif
430 
431 }
432 
434 {
435 #ifdef ATTRIB_MENU_SUPPORT
436 #endif
437 }
438 
440 {
442  // Update range to handle clip outliers
443  SetAxisRange();
444 }
445 
446 
448 {
449  if (m_Mode != eMode_Single)
450  return true;
452  return true;
453 }
454 
456 {
458  if (!m_gConfig)
459  return;
460  string name;
462  const CFeatList& feats(*CSeqFeatData::GetFeatList());
463  name = feats.GetStoragekey(GetFeatSubtype());
464  } else {
465  name = GetAnnotName();
466  }
467 
468 
470  CHistConfigDlg dlg;
471  dlg.SetConfig(GetHistParams());
472  dlg.SetConfigName(name);
473  dlg.SetRegistryPath("Dialogs.GraphRenderingOptions");
474  dlg.CreateX(NULL);
475  if (m_DlgHost) {
477  }
478  if (!m_Desc.empty())
479  dlg.SetHistName(m_Desc);
480  if (dlg.ShowModal() == wxID_OK) {
482  SetAxisRange();
484  }
485  if (m_DlgHost) {
487  }
488  }
489 
490 }
491 
492 
493 bool CHistogramGlyph::NeedTooltip(const TModelPoint& p, ITooltipFormatter& tt, string& t_title) const
494 {
495  if (m_Mode != eMode_Single)
496  return false;
497  GetTooltip(p, tt, t_title);
498  return true;
499 }
500 
501 void CHistogramGlyph::GetTooltip(const TModelPoint& p, ITooltipFormatter& tt, string& /*t_title*/) const
502 {
503  if (m_Mode != eMode_Single)
504  return;
505 
506  string value;
507 
510  value += " heatmap";
511  value[0] = toupper(value[0]);
512  if (!CSeqUtils::IsUnnamed(GetTitle())) {
513  value += " (" + GetTitle() + ")";
514  }
515  tt.AddRow(value);
516  } else { // it is graph
517 
518  if (!GetDesc().empty()) {
519  value = GetDesc();
520  /*NStr::ReplaceInPlace(tt, "&#xA;", "\n");
521  NStr::ReplaceInPlace(tt, "&#xa;", "\n");*/
522  tt.AddRow(value);
523  } else {
524  tt.AddRow("Graph:", GetTitle());
525  }
526 
527  bool check_data_points = false;
528  ITERATE(TMaps, map_iter, m_Maps) {
529  const TMap& densityMap = map_iter->second;
530  if (!densityMap.GetDataPoints().empty()) {
531  check_data_points = true;
532  break;
533  }
534  }
535 
536  if (check_data_points) {
537 
538  CRef<CHistParams> params = GetHistParams();
539  TModelUnit x = p.X();
540  TModelUnit y = p.Y();
542  SLogScaleData logscale(m_AxisMax, m_AxisMin, GetHeight(), params->m_Scale);
543 
544  ITERATE(TMaps, map_iter, m_Maps) {
545  const TMap& densityMap = map_iter->second;
546  for (size_t idx = 0; idx < densityMap.GetDataPoints().size(); ++idx) {
547  TModelPoint p = densityMap.GetDataPoint(idx);
548  double value = p.Y();
549  p.m_Y = x_MapValue(p.m_Y);
550  if (params->m_Scale != CHistParams::eLinear)
551  p.m_Y = logscale.MapValue(p.m_Y);
552  p = x_PointToWorld(p);
553  if (rect.PtInRect(p.X(), p.Y())) {
554  tt.AddRow("Value:", NStr::DoubleToString(value, 2));
555  return;
556  }
557  }
558  }
559  }
560  }
561 
562  // assume IsBackgroundJob returns false in Cgi mode
564  tt.AddRow();
565  tt.AddRow("Double click on the histogram to change settings");
566  }
567 }
568 
570 {
571 
572  TModelUnit scale_y = (m_AxisMin < 0 && m_AxisMax <= 0) ? m_AxisMin - m_AxisMax : m_AxisMax - m_AxisMin;
573  if (scale_y == 0)
574  return TModelPoint(p);
575 
576  TModelUnit x = p.X();
577  TModelUnit y = p.Y();
578 
579  CRef<CHistParams> params = GetHistParams();
580  if (params->m_Scale == CHistParams::eLinear) {
581 
582  TModelUnit y_ratio = min(1.0, fabs(m_AxisMax) / scale_y);
583  if (y_ratio > 0 && y_ratio < 1.) {
584  TModelUnit pos_height = y_ratio * GetHeight();
585  TModelUnit neg_height = GetHeight() - pos_height;
586  if (y >= neg_height) {
587  scale_y = GetAxisMax() / pos_height;
588  y /= scale_y;
589  y += neg_height;
590  } else {
591  scale_y = GetAxisMin() / neg_height;
592  y /= scale_y;
593  y += pos_height;
594  }
595  } else {
596  scale_y /= (TModelUnit)GetHeight();
597  y /= scale_y;
598  }
599  } else {
600  TModelUnit y_ratio = (m_AxisMin < 0 && m_AxisMax > 0) ? 0.5f : 1.0f;
601  if (y_ratio != 1.) {
602  TModelUnit h = y_ratio * GetHeight();
603  h = GetHeight() - h;
604  scale_y = (y >= h) ? 1 : -1;
605  y /= scale_y;
606  y += h;
607 
608  } else {
609  scale_y = (m_AxisMin < 0) ? -1. : 1;
610  y /= scale_y;
611  }
612  }
613  if (scale_y > 0)
614  y = GetHeight() - y;
615 
616  TModelUnit t_x = x;
617  TModelUnit t_y = y;
618  x_Local2World(t_x, t_y);
619  return TModelPoint(t_x, t_y);
620 }
621 
622 
624 {
625  label.clear();
626  if (IsCoverageGraph())
628  CRef<CHistParams> params = GetHistParams();
629  if (params->m_Scale != CHistParams::eLinear) {
630  if (!label.empty())
631  label += ", ";
633  label += " scaled";
634  }
635 }
636 
638 {
639 
640  _ASSERT(p_areas);
641  // Legen should go first
642  if (m_Legend) {
643  m_Legend->GetHTMLActiveAreas(p_areas);
644  }
645 
646  bool check_data_points = false;
647  ITERATE(TMaps, map_iter, m_Maps) {
648  const TMap& densityMap = map_iter->second;
649  if (!densityMap.GetDataPoints().empty()) {
650  break;
651  }
652  }
653  bool area_added = false;
654  if (check_data_points) {
655 
656  CRef<CHistParams> params = GetHistParams();
657  SLogScaleData logscale(m_AxisMax, m_AxisMin, GetHeight(), params->m_Scale);
658 
659  ITERATE(TMaps, map_iter, m_Maps) {
660  const TMap& densityMap = map_iter->second;
661  for (size_t idx = 0; idx < densityMap.GetDataPoints().size(); ++idx) {
662  TModelPoint p = densityMap.GetDataPoint(idx);
663  TModelUnit y = x_MapValue(p.Y());
664  if (params->m_Scale != CHistParams::eLinear)
665  y = logscale.MapValue(y);
666 
667  TModelUnit x = p.X();
669  CHTMLActiveArea area;
670  area.m_SeqRange = TSeqRange(p.X(), p.X());
671  x = m_Context->SeqToScreenX(pt.X());
672  // area.m_ID = GetAnnotName() + ":" + NStr::NumericToString(p.X());
674  x + kDataPointRadius, pt.Y() - kDataPointRadius);
676  area.m_Signature = "sig";
677  area.m_Descr = NStr::DoubleToString(p.Y(), 2);
678  p_areas->push_back(area);
679  area_added = true;
680  }
681  }
682  }
684 
685  for (const auto& outlier : m_Outliers) {
686  TModelPoint p(outlier.range.GetFrom(), outlier.y);
687  TModelPoint pt = x_PointToWorld(p);
688  CHTMLActiveArea area;
689  area.m_SeqRange = outlier.range;
690  auto x1 = m_Context->SeqToScreenX(outlier.range.GetFrom());
691  auto x2 = m_Context->SeqToScreenX(outlier.range.GetTo());
692  if (outlier.value > 0)
693  area.m_Bounds.Init(x1, pt.Y() + 5, x2, pt.Y() + 1);
694  else
695  area.m_Bounds.Init(x1, pt.Y() + 2, x2, pt.Y() - 2);
699  area.m_Signature = "otl";
700  area.m_Descr = "Outlier value: " + NStr::DoubleToString(outlier.value, 2);
701  p_areas->push_back(area);
702  }
703  }
704 
705  if (!area_added && m_Mode != eMode_Overlay) {
706  CHTMLActiveArea area;
708  area.m_PositiveStrand = true;
709 
710  CSeq_loc loc;
711  CSeq_interval& ival = loc.SetInt();
713  CConstRef<CSeq_id> seq_id = seq_ds->GetBioseqHandle().GetSeqId();
714  ival.SetId().Assign(*seq_id);
715 
716  TMaps::const_iterator first_map = m_Maps.begin();
717  int subtype = 0;
719  CRef<CHistParams> params = GetHistParams();
720  // All HistogramGlyphs tooltips should be embedded
721  // They still have to have correct signature as seqgraphic uses it to parse out title for remote tracks
722  // Histogram glyphs for remote tracks are expected to have empty m_Descr
723  // so that its tooltip can be created form GetTitle()
724 
730 
732  // This is track feature pile-up which can be rendered as histogram or heatmap
733  area.m_Descr =
735 
736  if (params->m_Type == CHistParams::eSmearBar || params->m_Type == CHistParams::eMergedBar)
737  area.m_Descr += " heatmap";
738  else
739  area.m_Descr += " distribution histogram";
740  area.m_Descr[0] = toupper(area.m_Descr[0]);
741 
743  subtype = GetFeatSubtype();
744 
745  ival.SetFrom(first_map->second.GetStart());
746  ival.SetTo(first_map->second.GetStop());
747  } else {
748  // This is track graph track or it can be single line graph create for feaures (dbavr track only???)
750  ival.SetFrom(0);
751  ival.SetTo(seq_ds->GetSequenceLength() - 1);
752  if (IsCoverageGraph())
753  x_GetLabel(area.m_Descr);
754  else {
755  area.m_Descr = GetDesc();
756  }
757  }
758  area.m_Signature =
760  GetTitle(),
762  subtype);
764  area.m_Signature = "fake|" + area.m_Signature;
765  }
766  //}
767  // a tooltip should be generated for histograms created by a remote file pipeline to avoid an additional roundtrip
768  if(isRmtBased()) {
769  string s;
770  string title;
772  tooltip->SetTrustedData(false);
773  GetTooltip(TModelPoint(-1, -1), *tooltip, title);
774  s = tooltip->Render();
775  string text = NStr::Replace(s, "\n", "<br/>");
776  area.m_Descr = text;
777  }
778  p_areas->push_back(area);
779 
780  if (IsCoverageGraph()) {
781  string label;
782  x_GetLabel(label);
783 
785  IRender& gl = GetGl();
786 
787  TModelRange vis_r = m_Context->IntersectVisible(this);
788  int view_width = m_Context->GetViewWidth();
789  if (view_width == 0)
790  view_width = m_Context->SeqToScreen(vis_r.GetLength());
791  view_width -= 10;
792 
793  auto right = view_width;
794  right -= (gl.TextWidth(&font, label.c_str()) + 4);
795 
796  TModelUnit left = 0;
797  TModelUnit top = 0;
798  x_Local2World(left, top);
799  CHTMLActiveArea label_area;
800 
802  label_area.m_Bounds.SetTop(top);
803  label_area.m_Bounds.SetBottom(top + gl.TextHeight(&font) + 2);
804  label_area.m_Bounds.SetLeft(-1);
805  label_area.m_Bounds.SetRight(right);
810  label_area.m_ID = label;
811  // required, but nonsense fields
812  label_area.m_PositiveStrand = true;
813  label_area.m_SeqRange.SetFrom(0);
814  label_area.m_SeqRange.SetTo(0);
815 
816  p_areas->emplace_back(label_area);
817  }
818 
819 
820  }
821 }
822 
823 
825 {
827  if (!m_gConfig)
828  return false;
829 
830  string name;
832  const CFeatList& feats(*CSeqFeatData::GetFeatList());
833  name = feats.GetStoragekey(GetFeatSubtype());
834  } else {
835  name = GetAnnotName();
836  }
837 
839  return false;
840  }
841 
842  return true;
843 }
844 
846 {
848 }
849 
850 
851 objects::CSeqFeatData::E_Choice CHistogramGlyph::GetFeatType() const
852 {
853  return objects::CSeqFeatData::GetTypeFromSubtype(m_Subtype);
854 }
855 
856 
857 void CHistogramGlyph::SetAnnotName(const string& name)
858 {
859  m_AnnotName = name;
860  if (NStr::StartsWith(m_AnnotName, "NA")) {
861  // In case it is a high level coverage graph, the
862  // annotation name has level number tagged at the
863  // end of the base annotation name, such as
864  // NA000008860.1@100 for NA000008860.1
865  // What we need here is the base annotation name
866  int level;
867  string base_name;
868  if (ExtractZoomLevel(name, &base_name, &level) ) {
869  m_AnnotName = base_name;
870  }
871  }
872  if(CSeqUtils::isRmtAnnotName(name)) {
873  m_RmtAnnotName = name;
874  }
875 }
876 
878 {
879  IRender& gl = GetGl();
880  CRef<CHistParams> params = GetHistParams();
881  TModelUnit top = GetTop();
882 
883  // Compute number of vertical ticks based on font height
886 
887  TDataType AxisMax = negative ? fabs(m_AxisMin) : fabs(m_AxisMax);
888  TModelUnit y_ratio = fabs(m_AxisMax - m_AxisMin) != 0 ?
890  if (y_ratio == 0.0f || y_ratio > 1.0f)
891  y_ratio = 1.0f;
892 
893  TModelUnit height = ceil(y_ratio * GetHeight());
894  if (negative && y_ratio != 1.0f) {
895  top += height;
896  height = GetHeight() - height;
897  }
898  TModelUnit bottom = top + height;
899 
900  bool forced_min_ticks = false;
901  int tick_n = floor(double(TModelUnit(height)/(TModelUnit(3)*font_height)));
902  if (tick_n < 2) {
903  forced_min_ticks = true;
904  tick_n = 2;
905  }
906 
907  TModelUnit dist_y = height / tick_n;
908  double axis_max = AxisMax;
909  double axis_min = y_ratio == 1.0f ? (negative ? fabs(m_AxisMax) : fabs(m_AxisMin)) : 0;
910  int precision = 0;
911 
912  // suppress precision (even it tick marks divide with a remainder) if distance between ticks
913  // is large enough that it wouldn't be noticable.
914  TModelUnit height_per_tick = (axis_max-axis_min)/TModelUnit(tick_n);
915  if (height_per_tick < 10)
916  precision = 1;
917 
918 
919  const CRgbaColor& r_c = params->m_RulerColor;
920  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.4f);
921 
922  for (size_t i=0; i<=(size_t)tick_n; ++i) {
923  m_Context->DrawLine(GetLeft(), top + dist_y*i, GetRight(), top + dist_y*i);
924  }
925 
926  int ruler_n = 6;
927  TModelUnit dist_x = GetWidth() / ruler_n;
929  if (dist_x < min_dist) {
930  dist_x = min_dist;
931  ruler_n = (int)(GetWidth() / dist_x);
932  }
933  TModelUnit label_off = m_Context->ScreenToSeq(1.0);
934 
935  TModelUnit x = GetLeft() + dist_x * 0.1;
936  for (; x < GetRight(); x += dist_x) {
937 
938  if (params->m_NeedRulerLabels || !m_gConfig->GetCgiMode()) {
939 
940  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.5f);
941  m_Context->DrawLine(x, top, x, bottom);
942 
943  gl.ColorC(params->m_LabelColor);
944  if (negative == false) {
945  if (axis_min != 0) {
946  m_Context->TextOut(&font, NStr::DoubleToString(axis_min).c_str(),
947  x + label_off,
948  bottom - 1, false);
949  }
950  } else {
951  if (axis_max != 0) {
952  m_Context->TextOut(&font, NStr::DoubleToString(-axis_max).c_str(),
953  x + label_off,
954  bottom - 1, false);
955  }
956  }
957 
958  // Draw values for ticks between min and max, unless the space is too narrow to fit (forced_min_ticks)
959  if (forced_min_ticks)
960  tick_n = 1;
961  for (size_t i=0; i<(size_t)tick_n; ++i) {
962  TModelUnit height = negative ?
963  TModelUnit(axis_max-axis_min)*(TModelUnit(i)/TModelUnit(tick_n))
964  : TModelUnit(axis_max) - TModelUnit(axis_max-axis_min)*(TModelUnit(i)/TModelUnit(tick_n));
965  if (height == 0)
966  continue;
967  // skip zero if it's already printed on the positive side
968  if (height == 0 && negative && y_ratio != 1.0)
969  continue;
970  // only show decimals if delta between ticks is low and delta >= 0.1
971  int current_precision = 0;
972  if (precision > 0 && height-floor(height) >= 0.1f)
973  current_precision = precision;
974  if (negative && height > 0)
975  height = -height;
976  m_Context->TextOut(&font, NStr::DoubleToString(height, current_precision).c_str(),
977  x + label_off, top + dist_y*i + gl.TextHeight(&font) + 1, false);
978  }
979  }
980  }
981 }
982 
983 
985 {
986  IRender& gl = GetGl();
987  CRef<CHistParams> params = GetHistParams();
988  TModelUnit top = GetTop();
989 
990  // to display in any of the log scales (regardless of what
991  // the underlying graph scale is)
992  // Compute number of vertical ticks based on font height
995  TModelUnit vertical_text_space_min = TModelUnit(2)*font_height;
996 
997  TDataType AxisMax = negative ? fabs(m_AxisMin) : fabs(m_AxisMax);
998  TModelUnit y_ratio = (m_AxisMin < 0 && m_AxisMax > 0) ? 0.5f : 1.0f;
999  TModelUnit height = y_ratio * GetHeight();
1000  if (negative && y_ratio != 1.0f) {
1001  top += height;
1002  height = GetHeight() - height;
1003  }
1004  TModelUnit bottom = top + height;
1005 
1006  double log_base = 10.0;
1007  double log_max = 0.0;
1008  double log_min = 0.0;
1009  double log_remainder = 0.0;
1010  double axis_max = AxisMax;
1011  double axis_min = y_ratio == 1.0f ? (negative ? fabs(m_AxisMax) : fabs(m_AxisMin)) : 0;
1012  int precision = 0;
1013 
1014  if (axis_max > FLT_EPSILON) {
1015  if (params->m_Scale == CHistParams::eLog10) {
1016  log_base = 10.0;
1017  log_max = log10((double)axis_max);
1018  log_min = log10((double)axis_min);
1019  }
1020  else if (params->m_Scale == CHistParams::eLog2) {
1021  log_base = 2.0;
1022  log_max = log((double)axis_max )/log( 2.0 ); //log2 not supported on windows
1023  log_min = log((double)axis_min )/log( 2.0 );
1024  }
1025  else { // eLoge
1026  log_base = M_NCBI_E;
1027  log_max = log((double)axis_max );
1028  log_min = log((double)axis_min );
1029  precision = 2;
1030  }
1031  }
1032 
1033  //log_max = ceil(log_max);
1034  log_remainder = log_max-floor(log_max);
1035  log_max = floor(log_max);
1036  log_min = max(0.0, ceil(log_min));
1037 
1038  int tick_n = (int)log_max;
1039  if (tick_n == 0) { // if value is <= 1
1040  tick_n = 1;
1041  log_remainder = 0.0;
1042  }
1043 
1044  // Ticks are in increments of the log scale (e.g. for 10: 10, 100, 1000)
1045  // but the top number is always axis_max which is unlikely to be a power
1046  // of the log value so top_y is the distance from axis_max down to the
1047  // first log value (log_max)
1048  TModelUnit top_y = height * (log_remainder/(log_max+log_remainder));
1049  TModelUnit dist_y = (height - top_y) / double(tick_n);
1050 
1051  const CRgbaColor& r_c = params->m_RulerColor;
1052 
1053  int ruler_n = 4;
1054  TModelUnit dist_x = GetWidth() / ruler_n;
1056  if (dist_x < min_dist) {
1057  dist_x = min_dist;
1058  ruler_n = (int)(GetWidth() / dist_x);
1059  }
1060  TModelUnit label_off = m_Context->ScreenToSeq(1.0);
1061 
1062  TModelUnit x = GetLeft() + dist_x * 0.1;
1063  bool draw_horizontal_lines = true;
1064  // outside loop: iterate from left to right
1065  for (; x < GetRight(); x += dist_x) {
1066 
1067  TModelUnit yval = TModelUnit(0);
1068  if (params->m_NeedRulerLabels) {
1069 
1070  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.5f);
1071  m_Context->DrawLine(x, top, x, bottom);
1072 
1073  gl.ColorC(params->m_LabelColor);
1074  if (negative == false) {
1075  if (axis_max != 0) {
1076  m_Context->TextOut(&font, NStr::DoubleToString(axis_max, precision).c_str(),
1077  x + label_off, top + gl.TextHeight(&font) + 1, false);
1078  }
1079  if (yval != 0) {
1080  m_Context->TextOut(&font, NStr::DoubleToString(yval).c_str(),
1081  x + label_off,
1082  bottom - 1, false);
1083  }
1084  } else {
1085  if (axis_max != 0) {
1086  m_Context->TextOut(&font, NStr::DoubleToString(-axis_max, precision).c_str(),
1087  x + label_off, bottom - 1, false);
1088  }
1089  }
1090  }
1091 
1092  if (draw_horizontal_lines) {
1093  // inner loop: iterate from top to bottom
1094  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.4f);
1095  m_Context->DrawLine(GetLeft(), top, GetRight(), top);
1096  if (y_ratio != 1.0f)
1097  m_Context->DrawLine(GetLeft(), bottom, GetRight(), bottom);
1098  }
1099 
1100  gl.ColorC(params->m_LabelColor);
1101  TModelUnit vertical_text_space = dist_y;
1102  TModelUnit vertical_line_space = dist_y;
1103  bool draw_unlabled_lines = (tick_n*dist_y-vertical_text_space_min*0.5) < vertical_text_space_min;
1104 
1105  // iterate from bottom to the top
1106  yval = log_base;
1107 
1108  // first line
1109  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.4f);
1110  m_Context->DrawLine(GetLeft(), bottom, GetRight(), bottom);
1111 
1112  for (int i=1; i<=tick_n; ++i) {
1113  // Don't write text on vertical ticks that are too close together. (or
1114  // too close to the bottom -0- bar). Allow a little less space (50%)
1115  // between very top (axis_max) and top tick
1116  TModelUnit y = negative ?
1117  top + dist_y*(TModelUnit)(i) : top + top_y + dist_y*(TModelUnit)(tick_n-i);
1118  TModelUnit bottom_gap = negative ? bottom - y : y - top ;
1119  if (vertical_text_space >= vertical_text_space_min &&
1120  bottom_gap >= vertical_text_space_min*0.5) {
1121 
1122  // Draw horizontal lines on on first pass through outer loop since
1123  // these to all the way across.
1124  if (draw_horizontal_lines) {
1125  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.4f);
1126  m_Context->DrawLine(GetLeft(), y, GetRight(), y);
1127  }
1128  if (yval != 0 && params->m_NeedRulerLabels) {
1129 
1130  gl.ColorC(params->m_LabelColor);
1131  if (negative) {
1132  m_Context->TextOut(&font, NStr::DoubleToString(-yval, precision).c_str(),
1133  x + label_off, y - 1, false);
1134  } else {
1135  m_Context->TextOut(&font, NStr::DoubleToString(yval, precision).c_str(),
1136  x + label_off, y + gl.TextHeight(&font) + 1, false);
1137  }
1138  }
1139  vertical_text_space = TModelUnit(0);
1140  vertical_line_space = TModelUnit(0);
1141  }
1142  // only draw some lines sometimes even if no room for text. This is only turned on
1143  // if there is no room for lables on intermediate lines.
1144  else if (draw_horizontal_lines && draw_unlabled_lines &&
1145  vertical_line_space > (vertical_text_space_min*0.5) &&
1146  bottom_gap >= vertical_text_space_min*0.5) {
1147  // Draw horizontal lines on on first pass through outer loop since
1148  // these to all the way across.
1149  gl.Color4f(r_c.GetRed(), r_c.GetGreen(), r_c.GetBlue(), 0.4f);
1150  m_Context->DrawLine(GetLeft(), y, GetRight(), y);
1151  vertical_line_space = TModelUnit(0);
1152  }
1153 
1154  vertical_text_space += dist_y;
1155  vertical_line_space += dist_y;
1156  yval *= log_base;
1157  }
1158  draw_horizontal_lines = false;
1159  }
1160 }
1161 
1162 
1164 {
1165  CRef<CHistParams> params = GetHistParams();
1166  int dir = (val < 0) ? -1 : 1;
1167  if (color != 0)
1168  *color = val >= 0 && !(m_AxisMin < 0 && m_AxisMax <= 0) ? &m_fgColor : &m_negColor;
1169  if (outlier != 0)
1170  *outlier = false;
1171 
1172  TDataType AxisMax = dir < 0 ? m_AxisMin : m_AxisMax;
1173  if (params->m_Scale == CHistParams::eLinear && params->m_ClipOutliers) {
1174  if ((dir < 0 && val < AxisMax) || (dir > 0 && val > AxisMax)) {
1175  if (outlier != 0)
1176  *outlier = true;
1177  val = fabs(AxisMax);
1178  }
1179  }
1180  // Convert to linear initially (even if display target is log)
1181  if (params->m_StoredScale == CHistParams::eLog10)
1182  val = pow(10.0, fabs(val));
1183  else if (params->m_StoredScale == CHistParams::eLog2)
1184  val = pow(2.0, fabs(val));
1185  else if (params->m_StoredScale == CHistParams::eLoge)
1186  val = pow(M_NCBI_E, fabs(val));
1187 
1188  // Clip outliers (only supported for linear graphs)
1189  TModelUnit y_curr = fabs(val);
1190  if (params->m_Scale == CHistParams::eLinear) {
1191  if (m_AxisMin >= 0 && m_AxisMax > 0) {
1192  y_curr -= m_AxisMin;
1193  y_curr = max(0., y_curr);
1194  } else if (m_AxisMin < 0 && m_AxisMax <= 0) {
1195  y_curr += m_AxisMax;
1196  }
1197  }
1198 
1199  if (dir < 0)
1200  y_curr = -y_curr;
1201  y_curr = min<TModelUnit>(y_curr, fabs(AxisMax));
1202  return y_curr;
1203 }
1204 
1205 void CHistogramGlyph::x_DrawDataPoints(const TMap& densityMap) const
1206 {
1207  IRender& gl = GetGl();
1208  CRef<CHistParams> params = GetHistParams();
1209  SLogScaleData logscale(m_AxisMax, m_AxisMin, GetHeight(), params->m_Scale);
1210 
1211  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1212  gl.Enable(GL_BLEND);
1213  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1214  gl.Enable(GL_LINE_SMOOTH);
1215  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1216  gl.LineWidth(0.5);
1217 
1219  bool all_pos = !(m_AxisMin < 0 && m_AxisMax <= 0); // all data are positive
1220 
1221  double null_val = x_MapValue(0);
1222  if (params->m_Scale != CHistParams::eLinear)
1223  null_val = logscale.MapValue(null_val);
1224 
1225  vector<TModelPoint> points;
1226  points.reserve(densityMap.GetDataPoints().size() + 2);
1227  vector<const CRgbaColor*> colors;
1228  colors.reserve(densityMap.GetDataPoints().size() + 2);
1229 
1230  TModelPoint first_point = densityMap.GetFirstPoint();
1231  if (params->m_SmoothCurve)
1232  points.push_back(TModelPoint(first_point.X(), x_MapValue(first_point.Y())));
1233  else
1234  points.push_back(TModelPoint(first_point.X() - ctx->GetOffset(), x_MapValue(first_point.Y())));
1235  colors.push_back(first_point.Y() >= 0 && all_pos ? &m_fgColor : &m_negColor);
1236 
1237  for (size_t idx = 0; idx < densityMap.GetDataPoints().size(); ++idx) {
1238  TModelPoint p = densityMap.GetDataPoint(idx);
1239  colors.push_back(p.Y() >= 0 && all_pos ? &m_fgColor : &m_negColor);
1240  if (params->m_SmoothCurve == false) {
1241  p.m_X -= ctx->GetOffset();
1242  }
1243  p.m_Y = x_MapValue(p.m_Y);
1244  points.push_back(p);
1245  }
1246  TModelPoint last_point = densityMap.GetLastPoint();
1247  if (params->m_SmoothCurve)
1248  points.push_back(TModelPoint(last_point.X(), x_MapValue(last_point.Y())));
1249  else
1250  points.push_back(TModelPoint(last_point.X() - ctx->GetOffset(), x_MapValue(last_point.Y())));
1251  colors.push_back(last_point.Y() >= 0 && all_pos ? &m_fgColor : &m_negColor);
1252 
1253  gl.Begin(params->m_Type == CHistParams::eLineGraph ? GL_LINE_STRIP : GL_TRIANGLE_STRIP);
1254 
1255 
1256  for (size_t i = 0; i < points.size(); ++i) {
1257  if (i == 0 || colors[i - 1] != colors[i])
1258  gl.ColorC(*colors[i]);
1259  if (params->m_Scale != CHistParams::eLinear)
1260  points[i].m_Y = logscale.MapValue(points[i].Y());
1261  if (params->m_SmoothCurve == false) {
1263 
1264  if (i > 0) {
1265  TModelUnit prev_y = points[i - 1].Y();
1266  TModelUnit curr_y = points[i].Y();
1267  if ((prev_y > 0 && curr_y < 0) || (prev_y < 0 && curr_y > 0)) {
1268  double m = (curr_y - prev_y) / (points[i].X() - points[i - 1].X());
1269  TModelUnit x = (-prev_y / m) + points[i - 1].X();
1270  prev_y > 0 ? gl.ColorC(m_fgColor) : gl.ColorC(m_negColor);
1271  if (params->m_Type == CHistParams::eHistogram)
1272  gl.Vertex2d(x, null_val);
1273  gl.Vertex2d(x, null_val);
1274  gl.ColorC(*colors[i]);
1275  }
1276  }
1277 
1278  if (params->m_Type == CHistParams::eHistogram)
1279  gl.Vertex2d(points[i].X(), null_val);
1280  gl.Vertex2d(points[i].X(), points[i].Y());
1282  if (i > 0) {
1283 
1284  TModelUnit prev_y = points[i - 1].Y();
1285  TModelUnit curr_y = points[i].Y();
1286 
1287  TModelUnit x = points[i - 1].X() + (points[i].X() - points[i - 1].X()) / 2;
1288 
1289  gl.ColorC(*colors[i - 1]);
1290  if (params->m_Type == CHistParams::eHistogram)
1291  gl.Vertex2d(points[i - 1].X(), null_val);
1292  gl.Vertex2d(points[i - 1].X(), prev_y);
1293 
1294  if (params->m_Type == CHistParams::eHistogram)
1295  gl.Vertex2d(x, null_val);
1296  gl.Vertex2d(x, prev_y);
1297 
1298  if ((prev_y > 0 && curr_y < 0) || (prev_y < 0 && curr_y > 0)) {
1299 
1300  if (params->m_Type == CHistParams::eHistogram)
1301  gl.Vertex2d(x, null_val);
1302  gl.Vertex2d(x, prev_y);
1303 
1304  if (params->m_Type == CHistParams::eHistogram)
1305  gl.Vertex2d(x, null_val);
1306  gl.Vertex2d(x, null_val);
1307  }
1308  gl.ColorC(*colors[i]);
1309 
1310  if (params->m_Type == CHistParams::eHistogram)
1311  gl.Vertex2d(x, null_val);
1312  gl.Vertex2d(x, curr_y);
1313 
1314  if (params->m_Type == CHistParams::eHistogram)
1315  gl.Vertex2d(points[i].X(), null_val);
1316  gl.Vertex2d(points[i].X(), curr_y);
1317 
1318  } else {
1319  TModelUnit x = max(0., points[0].X());
1320  if (params->m_Type == CHistParams::eHistogram)
1321  gl.Vertex2d(x, null_val);
1322  gl.Vertex2d(x, points[i].Y());
1323  }
1324  }
1325  }
1326  }
1327  gl.End();
1328 
1329  if (params->m_SmoothCurve)
1330  x_DrawSmoothCurve(points);
1331 
1332  // draw values
1333  TModelUnit radius_x = ctx->ScreenToSeq(kDataPointRadius);
1334  TModelUnit radius_y = kDataPointRadius;
1335  // TModelUnit radius_x_inner = ctx->ScreenToSeq(kDataPointRadius - 1.);
1336  // TModelUnit radius_y_inner = kDataPointRadius - 1.;
1337 
1338  if (params->m_Scale == CHistParams::eLinear) {
1339  TModelUnit h = fabs(GetAxisMax() - GetAxisMin()) + 1;
1340  radius_y *= h / (TModelUnit)GetHeight();
1341  // radius_y_inner *= h / (TModelUnit)GetHeight();
1342  }
1343  TModelUnit t = 2 * 3.1415926;
1344  CRgbaColor* color = 0;
1345  bool outlier = false;
1346  for (size_t idx = 0; idx < densityMap.GetDataPoints().size(); ++idx) {
1347  TModelPoint p = densityMap.GetDataPoint(idx);
1348  p.m_Y = x_MapValue(p.m_Y, &color, &outlier);
1349  if (outlier)
1350  color = &params->m_OutlierColor;
1351  if (params->m_Scale != CHistParams::eLinear)
1352  p.m_Y = logscale.MapValue(p.m_Y);
1353  p.m_X -= ctx->GetOffset();
1354 
1355  {
1356  gl.ColorC(*color);
1357  TModelUnit f = 0;
1358  gl.Begin(GL_TRIANGLE_FAN);
1359  gl.Vertex2d(p.X(), p.Y());
1360  TModelUnit step = (t - f) * 0.02;
1361  for (; f < t + step * 0.02; f += step) {
1362  gl.Vertex2d(p.X() - radius_x * cos(f), p.Y() - radius_y * sin(f));
1363  }
1364  gl.End();
1365  }
1366 
1367  //if (params->m_DrawBg)
1368  /*
1369  {
1370 
1371  gl.ColorC(params->m_bgColor);
1372  TModelUnit f = 0;
1373  gl.Begin(GL_TRIANGLE_FAN);
1374  gl.Vertex2d(p.X(), p.Y());
1375  TModelUnit step = (t - f) * 0.02;
1376  for (; f < t + step * 0.02; f += step) {
1377  gl.Vertex2d(p.X() - radius_x_inner * cos(f), p.Y() - radius_y_inner * sin(f));
1378  }
1379  gl.End();
1380  }
1381  */
1382 
1383  if (outlier) {
1384  gl.LineWidth(1.0);
1385  gl.Begin(GL_LINES);
1386  gl.Vertex2d(p.X(), p.Y());
1387  gl.Vertex2d(p.X(), null_val);
1388  gl.End();
1389  }
1390  }
1391  gl.Disable(GL_BLEND);
1392  gl.Disable(GL_LINE_SMOOTH);
1393  gl.LineWidth(1.0);
1394 }
1395 
1396 void CHistogramGlyph::x_DrawSmoothCurve(vector<TModelPoint>& points) const
1397 {
1398  if (points.empty())
1399  return;
1400 
1401  vector<double> x_points;
1402  x_points.reserve(points.size());
1403  vector<double> y_points;
1404  y_points.reserve(points.size());
1405  CGlPane* orig_pane = m_Context->GetGlPane();
1406  auto from = orig_pane->ProjectX(points.front().X());
1407  auto to = orig_pane->ProjectX(points.back().X());
1408  if (from > to) {
1409  swap(from, to);
1410  }
1411  double y_min = numeric_limits<double>::max(), y_max = numeric_limits<double>::min();
1412  size_t idx = 0;
1413  for (const auto& p : points) {
1414  auto x = orig_pane->ProjectX(p.X());
1415  const auto& y = p.Y();
1416  y_max = max<double>(y, y_max);
1417  y_min = min<double>(y, y_min);
1418  bool new_value = (idx == 0) || (m_Context->IsFlippedStrand() && x_points[idx - 1] > x) || (!m_Context->IsFlippedStrand() && x_points[idx - 1] < x);
1419  if (new_value) {
1420  x_points.push_back(x);
1421  y_points.push_back(y);
1422  ++idx;
1423  } else {
1424  if (fabs(y) > fabs(y_points[idx - 1]))
1425  y_points[idx - 1] = y;
1426  }
1427  }
1428  if (m_Context->IsFlippedStrand()) {
1429  reverse(x_points.begin(), x_points.end());
1430  reverse(y_points.begin(), y_points.end());
1431  }
1432  CRef<CHistParams> params = GetHistParams();
1433  Splines::PchipSpline spline;
1434  spline.build(x_points, y_points);
1435 
1436  IRender& gl = GetGl();
1437  gl.PushMatrix();
1438  gl.LoadIdentity();
1439  orig_pane->Close();
1440  CGlPane pane(*orig_pane);
1441  auto rcVP = pane.GetViewport();
1442  //pane.Close();
1443  TModelUnit t = 0;
1444  TModelUnit t_x = 0;
1445  x_Local2World(t_x, t);
1446 
1447  t = (rcVP.Top() - t);
1448  TVPRect vp_rect(rcVP.Left(), t - GetHeight(), rcVP.Right(), t + GetTop());
1449  pane.SetViewport(vp_rect);
1450  pane.OpenPixels();
1451  float height = vp_rect.Height();
1452  double scale = 1.0;
1453  if (params->m_Scale == CHistParams::eLinear) {
1454  double h = fabs(GetAxisMax() - GetAxisMin());
1455  scale = GetHeight();
1456  scale /= h;
1457  }
1458  auto bottom = vp_rect.Bottom() + 1;
1459  gl.Translatef(0.0f, bottom, 0.0f);
1460  gl.Scalef(1.0f, scale, 1.0f);
1461 
1462  if (params->m_Scale == CHistParams::eLinear) {
1463  if (m_AxisMax < 0)
1464  gl.Translatef(0.0, m_AxisMax, 0.0);
1465  else if (m_AxisMin < 0)
1466  gl.Translatef(0.0, -m_AxisMin, 0.0);
1467  } else {
1468  if (m_AxisMax <= 0)
1469  gl.Translatef(0.0, height, 0.0);
1470  else if (m_AxisMin < 0 && m_AxisMax > 0)
1471  gl.Translatef(0.0, height / 2., 0.0);
1472  }
1473  if (params->m_Type == CHistParams::eHistogram) {
1474  CRgbaColor top_colors[2] = { m_fgColor, m_negColor };
1475  CRgbaColor bottom_colors[2] = { m_fgColor, m_negColor };
1476  bottom_colors[0].Lighten(0.55f);
1477  bottom_colors[1].Lighten(0.55f);
1478  CRgbaColor middle_colors[2] = {
1479  CRgbaColor::Interpolate(top_colors[0], bottom_colors[0], 0.6f),
1480  CRgbaColor::Interpolate(top_colors[1], bottom_colors[1], 0.6f)
1481  };
1482 
1483  TModelUnit model_heights[2];
1484  if (params->m_Scale == CHistParams::eLinear) {
1485  if (m_AxisMin < 0) {
1486  model_heights[0] = GetAxisMax();
1487  model_heights[1] = fabs(GetAxisMin());
1488  } else {
1489  model_heights[0] = model_heights[1] = fabs(GetAxisMax() - GetAxisMin());
1490  }
1491  } else {
1492  model_heights[0] = model_heights[1] = m_AxisMin < 0 ? height * 0.5f : height;
1493  }
1494  gl.ShadeModel(GL_SMOOTH);
1495  gl.Begin(GL_LINES);
1496 
1497  for (TSignedSeqPos pos = from; pos <= to; ++pos) {
1498  //auto y = alglib::spline1dcalc(s, pos);
1499  float y = spline(pos);
1500  //y = (y <= y_min) ? y_min : (y > y_max) ? y_max : y;
1501  if (y <= y_min)
1502  y = y_min;
1503  else if (y >= y_max)
1504  y = y_max;
1505 
1506  size_t idx = y < 0 ? 1 : 0;
1507  int dir = y < 0 ? -1 : 1;
1508  CRgbaColor middle_c = middle_colors[idx];
1509  auto model_hh = model_heights[idx] * 0.3;
1510  if (fabs(y) > model_hh) {
1511  auto middle_y = model_hh * dir;
1512 
1513  gl.ColorC(middle_c);
1514  gl.Vertex2f(pos, middle_y);
1515 
1516  float alpha = (fabs(y) - model_hh) / (model_heights[idx] - model_hh);
1517  gl.ColorC(CRgbaColor::Interpolate(top_colors[idx], middle_c, alpha));
1518  gl.Vertex2f(pos, y);
1519  y = middle_y;
1520  } else {
1521  middle_c = CRgbaColor::Interpolate(middle_c, bottom_colors[idx], fabs(y) / model_hh);
1522  }
1523  gl.ColorC(bottom_colors[idx]);
1524  gl.Vertex2f(pos, 0);
1525  gl.ColorC(middle_c);
1526  gl.Vertex2f(pos, y);
1527  }
1528  gl.End();
1529  gl.ShadeModel(GL_FLAT);
1530 
1531  } else {
1532  gl.Enable(GL_LINE_SMOOTH);
1533  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1534  if (m_gConfig->GetCgiMode()) {
1535  if (m_Context->GetScale() > 3)
1536  gl.LineWidth(0.5);
1537  else if (m_Context->GetScale() > 1. / 4.)
1538  gl.LineWidth(1.5);
1539  else
1540  gl.LineWidth(2);
1541  }
1542  gl.Begin(GL_LINE_STRIP);
1543  TModelUnit prev_y = 0;
1544  for (TSignedSeqPos pos = from; pos <= to; ++pos) {
1545  float y = spline(pos);
1546  if (y <= y_min)
1547  y = y_min;
1548  else if (y >= y_max)
1549  y = y_max;
1550 
1551  if (pos > 0) {
1552  if ((y < 0 && prev_y > 0) || (prev_y < 0 && y > 0)) {
1553  gl.Vertex2d(pos, 0);
1554  gl.ColorC(y < 0 ? m_negColor : m_fgColor);
1555  }
1556  } else {
1557  gl.ColorC(y < 0 ? m_negColor : m_fgColor);
1558  }
1559  gl.Vertex2d(pos, y);
1560  prev_y = y;
1561  }
1562  gl.End();
1563  gl.Disable(GL_LINE_SMOOTH);
1564  }
1565  gl.PopMatrix();
1566  orig_pane->OpenOrtho();
1567 }
1568 
1569 
1571 {
1572  const TMap& densityMap = map_iter->second;
1573  TMap::runlen_iterator seg_it = densityMap.RunLenBegin();
1574  if (!seg_it)
1575  return;
1576 
1577  if (!densityMap.GetDataPoints().empty()) {
1578  x_DrawDataPoints(densityMap);
1579  return;
1580  }
1581 
1582  IRender& gl = GetGl();
1583  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1584 
1585  CRef<CHistParams> params = GetHistParams();
1586  SLogScaleData logscale(m_AxisMax, m_AxisMin, GetHeight(), params->m_Scale);
1587 
1588  TSeqPos prev_x = 0;
1589  TModelUnit prev_y = 0;
1590  m_Outliers.clear();
1591 
1592  if (params->m_Type == CHistParams::eLineGraph) {
1593 
1594  gl.Enable(GL_LINE_SMOOTH);
1595  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1596  if (m_gConfig->GetCgiMode()) {
1597  if (m_Context->GetScale() > 3)
1598  gl.LineWidth(0.5);
1599  else if (m_Context->GetScale() > 1. / 4.)
1600  gl.LineWidth(1.5);
1601  else
1602  gl.LineWidth(2);
1603  }
1604  gl.Begin(GL_LINE_STRIP);
1605  } else if (params->m_Type == CHistParams::eHistogram) {
1606  gl.ShadeModel(GL_SMOOTH);
1607  gl.Begin(GL_QUADS);
1608  }
1609  // int pix_per_base = 1. / m_Context->GetScale();
1610  // int fit_step = max<int>(params->m_FitStep, pix_per_base);
1611  int fit_step = params->m_FitStep;
1612  vector<TModelPoint> points;
1613 
1614  // pre-calculated variables for Histogram rendering
1615  CRgbaColor top_colors[2] = { m_fgColor, m_negColor };
1616  CRgbaColor bottom_colors[2] = { m_fgColor, m_negColor };
1617  CRgbaColor middle_colors[2];
1618  TModelUnit model_heights[2];
1619  TModelUnit model_heights3[2];
1620 
1621  if (params->m_Scale == CHistParams::eLinear) {
1622  if (m_AxisMin < 0 && m_AxisMax > 0) {
1623  model_heights[0] = GetAxisMax();
1624  model_heights[1] = fabs(GetAxisMin());
1625  } else {
1626  model_heights[0] = model_heights[1] = fabs(GetAxisMax() - GetAxisMin());
1627  }
1628  } else {
1629  model_heights[0] = model_heights[1] = m_AxisMin < 0 ? GetHeight() * 0.5f : GetHeight();
1630  }
1631  if (params->m_Type == CHistParams::eHistogram) {
1632  bottom_colors[0].Lighten(0.55f);
1633  bottom_colors[1].Lighten(0.55f);
1634  middle_colors[0] = CRgbaColor::Interpolate(top_colors[0], bottom_colors[0], 0.6f);
1635  middle_colors[1] = CRgbaColor::Interpolate(top_colors[1], bottom_colors[1], 0.6f);
1636  model_heights3[0] = model_heights[0] * 0.3f;
1637  model_heights3[1] = model_heights[1] * 0.3f;
1638  }
1639 
1640  for (; seg_it; seg_it.Advance()) {
1641  TSeqPos f = seg_it.GetSeqPosition();
1642  TSeqPos t = seg_it.GetSeqRunEndPosition();
1643  if (f == t)
1644  continue;
1645  if (prev_x >= t) {
1646  t = prev_x + 1;
1647  }
1648  if (prev_x != 0) {
1649  if ((eRenderSVG == gl.GetApi()) && (params->m_Type == CHistParams::eHistogram)) {
1650  gl.End();
1651  gl.Begin(GL_QUADS);
1652  }
1653  }
1654 
1655  TModelUnit val = seg_it.GetValue();
1656  // zero all the way
1657  if (val == TModelUnit(0)
1658  && seg_it.GetPosition() == 0
1659  && seg_it.GetRunLength() == densityMap.GetBins())
1660  continue;
1661  if (val == densityMap.GetDefVal())
1662  val = 0;
1663  //continue;
1664 
1665  int dir = (val < 0) ? -1 : 1;
1666  size_t idx = (val < 0) ? 1 : 0;
1667  CRgbaColor* curr_color = 0;
1668  bool outlier = false;
1669  TModelUnit y_curr = x_MapValue(val, &curr_color, &outlier);
1670  gl.ColorC(*curr_color);
1671  if (params->m_Scale != CHistParams::eLinear) {
1672  y_curr = logscale.MapValue(y_curr);
1673  }
1674  //m_Context->DrawQuad(f, y_curr, t, 0.0);
1675  // If x1 and x2 are projected onto the same pixel on screen.
1676  // We simply draw aline instead of a quad.
1677  TModelUnit x1 = f;
1678  TModelUnit x2 = t;
1679  if (fabs(x2 - x1) < m_Context->GetScale()) {
1680  TModelUnit mid = (x2 + x1) / TModelUnit(2.0);
1681  x1 = mid - m_Context->GetScale() / (TModelUnit)2.0;
1682  x2 = mid + m_Context->GetScale() / (TModelUnit)2.0;
1683  }
1684  if (outlier) {
1685  TModelUnit y = model_heights[idx];
1686  if (dir < 0)
1687  y = GetAxisMin() >= 0 ? 0 : -model_heights[idx];
1688  // TODO
1689  if (false && !m_Outliers.empty()
1690  && m_Outliers.back().range.GetTo() == x1
1691  && m_Outliers.back().y == y
1692  && (!IsOutlierTooltips(*m_Context) || m_Outliers.back().value == val)) {
1693  m_Outliers.back().range.SetTo(x2);
1694  }
1695  else {
1696  SOutlier s = { TSeqRange(x1, x2), y, val };
1697  m_Outliers.push_back(s);
1698  }
1699  }
1700  if (params->m_SmoothCurve) {
1701  points.emplace_back(x1, y_curr);
1702  if (x2 > x1) {
1703  auto pix_len = (x2 - x1);
1704  double step_len = fit_step * m_Context->GetScale();
1705  if (step_len == 0)
1706  step_len = pix_len;
1707  int steps = pix_len / step_len;
1708  for (size_t i = 1; i < steps; ++i) {
1709  points.emplace_back(x1 + i * step_len, y_curr);
1710  }
1711  points.emplace_back(x2, y_curr);
1712  }
1713  } else {
1714  x1 -= m_Context->GetOffset();
1715  x2 -= m_Context->GetOffset();
1716 
1717  if (params->m_Type == CHistParams::eHistogram) {
1718  CRgbaColor middle_c = middle_colors[idx];
1719  auto y = fabs(y_curr);
1720  if (y > model_heights3[idx]) {
1721  auto middle_y = model_heights3[idx] * dir;
1722  gl.ColorC(middle_c);
1723  gl.Vertex2f(x1, middle_y);
1724  gl.Vertex2f(x2, middle_y);
1725  float alpha = (y - model_heights3[idx]) / (model_heights[idx] - model_heights3[idx]);
1726  gl.ColorC(CRgbaColor::Interpolate(top_colors[idx], middle_c, alpha));
1727  gl.Vertex2f(x2, y_curr);
1728  gl.Vertex2f(x1, y_curr);
1729  y_curr = middle_y;
1730  }
1731  else {
1732  middle_c = CRgbaColor::Interpolate(middle_c, bottom_colors[idx], y / model_heights3[idx]);
1733  }
1734  gl.ColorC(bottom_colors[idx]);
1735  gl.Vertex2f(x1, 0);
1736  gl.Vertex2f(x2, 0);
1737  gl.ColorC(middle_c);
1738  gl.Vertex2f(x2, y_curr);
1739  gl.Vertex2f(x1, y_curr);
1740  } else {
1741  if ((prev_y > 0 && y_curr < 0) || (prev_y < 0 && y_curr > 0)) {
1742  double m = (y_curr - prev_y) / (f - prev_x);
1743  f = (-prev_y / m) + prev_x;
1744  prev_y > 0 ? gl.ColorC(m_fgColor) : gl.ColorC(m_negColor);
1745  gl.Vertex2d(f - m_Context->GetOffset(), 0);
1746  gl.ColorC(*curr_color);
1747  }
1748  gl.Vertex2d(f - m_Context->GetOffset(), y_curr);
1749  if (t > f)
1750  gl.Vertex2d(t - m_Context->GetOffset(), y_curr);
1751  }
1752  }
1753 
1754  prev_y = y_curr;
1755  prev_x = t;
1756  }
1757  if (params->m_Type == CHistParams::eLineGraph) {
1758  gl.End();
1759  gl.Disable(GL_LINE_SMOOTH);
1760  } else if (params->m_Type == CHistParams::eHistogram) {
1761  gl.End();
1762  gl.ShadeModel(GL_FLAT);
1763  }
1764  gl.LineWidth(1.0);
1765 
1766  if (params->m_SmoothCurve)
1767  x_DrawSmoothCurve(points);
1768 
1769  if (!m_Outliers.empty()) {
1770  float o_min = numeric_limits<float>::max();
1771  float o_max = numeric_limits<float>::min();
1772  for (const auto& o : m_Outliers) {
1773  if (o.value > o_max)
1774  o_max = o.value;
1775  if (o.value < o_min)
1776  o_min = o.value;
1777  }
1778 
1779  TModelUnit one_pix_x = m_Context->ScreenToSeq(1.);
1780 
1781  float h = fabs(GetAxisMax() - GetAxisMin());
1782  TModelUnit three_pix_y = (3. * h) / GetHeight();
1783 
1784  gl.ColorC(params->m_OutlierColor);
1785  gl.Begin(GL_QUADS);
1786  for (const auto& o : m_Outliers) {
1787  TModelUnit three_pix = three_pix_y;
1788  if (o.value < 0)
1789  three_pix = -three_pix;
1790  auto x1 = o.range.GetFrom() - m_Context->GetOffset();
1791  auto x2 = o.range.GetTo() - m_Context->GetOffset();
1792  if (m_Context->SeqToScreen(o.range.GetLength()) < 2) {
1793  x1 -= one_pix_x;
1794  x2 += one_pix_x;
1795  }
1796  float factor = o.value / (o.value >= 0 ? o_max : o_min);
1797  if (IsOutlierTooltips(*m_Context)) {
1798  CRgbaColor cl(params->m_OutlierColor);
1799  cl.Lighten(1. - factor);
1800  gl.ColorC(cl);
1801  }
1802  gl.Vertex2d(x1, o.y);
1803  gl.Vertex2d(x2, o.y);
1804  gl.Vertex2d(x2, o.y - three_pix);
1805  gl.Vertex2d(x1, o.y - three_pix);
1806  }
1807  gl.End();
1808  }
1809 }
1810 
1811 
1812 void CHistogramGlyph::DrawGrid(bool include_background) const
1813 {
1814  IRender& gl = GetGl();
1815  CRef<CHistParams> params = GetHistParams();
1816  if (params->m_DrawBg) {
1817  gl.ColorC(params->m_bgColor);
1818  const TModelRect& rcm = GetModelRect();
1819  m_Context->DrawQuad(rcm);
1820  }
1821  if (params->m_NeedRuler &&
1822  (params->m_Type == CHistParams::eHistogram ||
1823  params->m_Type == CHistParams::eLineGraph) ) {
1824 
1825  CGlAttrGuard guard(GL_LINE_BIT);
1826  gl.Disable(GL_LINE_SMOOTH);
1827  gl.LineWidth(1.);
1828  if (params->m_Scale == CHistParams::eLinear) {
1829  if (m_AxisMin < 0)
1830  x_DrawLinearRuler(true);
1831  if (m_AxisMax > 0)
1832  x_DrawLinearRuler(false);
1833  } else {
1834  if (m_AxisMin < 0)
1835  x_DrawLogRuler(true);
1836  if (m_AxisMax > 0)
1837  x_DrawLogRuler(false);
1838  }
1839  gl.Enable(GL_LINE_SMOOTH);
1840  }
1841 }
1842 
1844 {
1846 
1847  IRender& gl = GetGl();
1848  // draw smear bar
1849  CRgbaColor color_max = config.m_SmearColorMax;
1850  CRgbaColor color_min = config.m_SmearColorMin;
1851 
1852  const TMap& densityMap = map_iter->second;
1853  float l_scale = (densityMap.GetMax() - densityMap.GetMin()) + 1;;
1854  if (l_scale > 0.0f) {
1855  // do pre-division
1856  l_scale = 1.0f / l_scale;
1857  }
1858  TModelUnit top = GetTop();
1859  TModelUnit bottom = top + GetHeight();
1860  if (m_Legend)
1861  bottom -= (m_Legend->GetHeight() + kLegenPadding);
1863  config.m_Colors.find(map_iter->first);
1864  if (c_iter != config.m_Colors.end()) {
1865  color_max = c_iter->second;
1866  color_max.SetAlpha(0.9f);
1867  color_min = color_max;
1868  color_min.Lighten(0.5f);
1869  color_min.SetAlpha(0.9f);
1870  }
1871  TMap::runlen_iterator seg_it = densityMap.RunLenBegin();
1872  for (; seg_it; seg_it.Advance()) {
1873  TModelUnit value = seg_it.GetValue();
1874  if (value == 0 || value == densityMap.GetDefVal())
1875  continue;
1876 
1877  TSeqPos f = seg_it.GetSeqPosition();
1878  TSeqPos t = seg_it.GetSeqRunEndPosition();
1879 
1880  // float score = (value - GetAxisMin()) * l_scale;
1881  float score = 0;
1882  if (GetAxisMin() < 0) {
1883  score = fabs(value) * l_scale * 0.5;
1884  if (value > 0)
1885  score += 0.5;
1886  else
1887  score = 0.5 - score;
1888  } else {
1889  if (m_BinSize > 0) {
1890  score = int(value / m_BinSize);
1891  score /= m_NumBins - 1;
1892 
1893  } else {
1894  score = (value - GetAxisMin()) * l_scale;
1895  }
1896 
1897  }
1898  score = max(0.0f, score);
1899  score = min(1.0f, score);
1900  CRgbaColor color(CRgbaColor::Interpolate(color_max, color_min, score));
1901  gl.ColorC(color);
1902  // draw our segment as quad
1903  m_Context->DrawQuad(f, top, t, bottom);
1904  }
1905 
1906  if (m_Legend && m_gConfig && !m_gConfig->GetCgiMode())
1907  m_Legend->Draw();
1908 }
1909 
1911 {
1912  IRender& gl = GetGl();
1913 
1914  if (m_Maps.size() > 1 && config.m_Colors.count(map_iter->first) > 0) {
1915  CHistParams::TColorSet::const_iterator c_iter = config.m_Colors.find(map_iter->first);
1916  m_fgColor = c_iter->second;
1917  } else {
1918  m_fgColor = config.m_fgColor;
1919  }
1920  if (m_Mode == eMode_Overlay && config.m_Type == CHistParams::eHistogram && m_fgColor.GetAlpha() == 1.f)
1921  m_fgColor.SetAlpha(0.75f);
1922  float scale = 1.0;
1923  if (config.m_Scale == CHistParams::eLinear) {
1924  float h = fabs(GetAxisMax() - GetAxisMin());
1925  if (h > 0.0)
1926  h = 1.0f / h;
1927  scale = h * GetHeight();
1928  }
1929  gl.PushAttrib(GL_ALL_ATTRIB_BITS);
1930  gl.PushMatrix();
1931  gl.LineWidth(1.0);
1932 
1933  TModelUnit bottom = GetTop() + GetHeight();
1934 
1935  if (m_AxisMin < 0 && m_AxisMax <= 0) {
1936  //gl.PushMatrix();
1937  //gl.Translatef(0.0f, top, 0.0f);
1938  //gl.ColorC(m_negColor);
1939  // m_Context->DrawLine(rcm.Left(), 0.0, rcm.Right(), 0.0);
1940  //gl.PopMatrix();
1941  gl.Translatef(0.0f, bottom, 0.0f);
1942  } else {
1943  gl.Translatef(0.0f, bottom, 0.0f);
1944  //gl.ColorC(m_fgColor);
1945  //m_Context->DrawLine(rcm.Left(), 0.0, rcm.Right(), 0.0);
1946  }
1947 
1948  gl.Scalef(1.0f, -scale, 1.0f);
1949 
1950  if (config.m_Scale == CHistParams::eLinear) {
1951  if (m_AxisMax < 0)
1952  gl.Translatef(0.0, m_AxisMax, 0.0);
1953  else if (m_AxisMin < 0)
1954  gl.Translatef(0.0, -m_AxisMin, 0.0);
1955  } else {
1956  if (m_AxisMax <= 0)
1957  gl.Translatef(0.0, GetHeight(), 0.0);
1958  else if (m_AxisMin < 0 && m_AxisMax > 0)
1959  gl.Translatef(0.0, GetHeight() / 2, 0.0);
1960  }
1961 
1962  x_DrawGraph(map_iter);
1963  gl.PopMatrix();
1964  gl.PopAttrib();
1965 }
1966 
1967 
1968 
1970 {
1971  if (m_Maps.empty())
1972  return;
1973  _ASSERT(m_Context);
1974  IRender& gl = GetGl();
1975  TModelRect rcm = GetModelRect();
1976  CRef<CHistParams> params = GetHistParams();
1977  if (m_Mode == eMode_Single && params->m_DrawBg) {
1978  gl.ColorC(params->m_bgColor);
1979  m_Context->DrawQuad(rcm);
1980  }
1981 
1982 #ifdef ATTRIB_MENU_SUPPORT
1983  // For debugging - allows the standard-deviation threshold for
1984  // clipping to be updated dynamically
1985  params->m_SDeviationThreshold = m_SDMult;
1986  const_cast<CHistogramGlyph*>(this)->SetAxisRange();
1987 #endif
1988 
1989  TSeqRange range = GetRange();
1990  TModelUnit two_pix_size = m_Context->ScreenToSeq(2.0);
1991  if (range.GetLength() < two_pix_size) {
1992  TModelUnit top = GetTop();
1993  TModelUnit bottom = top + GetHeight();
1994 
1995  // bar is less then 2 pixel. Just draw a background
1996  gl.ColorC(params->m_fgColor);
1997  m_Context->DrawQuad(range.GetFrom(), top,
1998  range.GetFrom() + two_pix_size, bottom);
1999  return;
2000  }
2001  m_negColor = params->m_fgNegColor;
2002 
2003  CGlAttrGuard guard(GL_LINE_BIT | GL_LIGHTING_BIT);
2004  gl.Disable(GL_LINE_SMOOTH);
2005 
2006  {
2007  CGlAttrGuard guard(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
2008  gl.Enable(GL_BLEND);
2009  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2010 
2011  ITERATE(TMaps, map_iter, m_Maps) {
2012  if (params->m_Type == CHistParams::eSmearBar || params->m_Type == CHistParams::eMergedBar) {
2013  x_DrawHeatMap(map_iter, *params);
2014  } else { // draw line graph or histogram
2015  x_DrawGraphMap(map_iter, *params);
2016  }
2017  }
2018  }
2019 
2020  if (m_Mode == eMode_Single)
2021  DrawGrid(false);
2022 
2023  // Draw selection
2024  if (IsSelected()) {
2025  m_Context->DrawSelection(rcm);
2026  }
2027 
2028  if (!m_gConfig->GetCgiMode() && IsCoverageGraph()) {
2029  string label;
2030  x_GetLabel(label);
2031  _ASSERT(!label.empty());
2032  auto pane = m_Context->GetGlPane();
2034  auto w = gl.TextWidth(&font, label.c_str());
2035  auto h = gl.TextHeight(&font);
2036  const TModelRect& vr = pane->GetVisibleRect();
2037  auto one_px = m_Context->ScreenToSeq(1);
2038  auto x = vr.Right() - ((w + 16) * one_px);
2039  auto y = vr.Top() + h + 2;
2040  gl.Color3f(0.f, 0.f, 0.f);
2041  m_Context->TextOut(&font, label.c_str(), x, y, false);
2042  }
2043 
2044  gl.Enable(GL_LINE_SMOOTH);
2045 }
2046 
2048 {
2049  if (!x_HasLegend()) {
2050  if (m_Legend)
2051  m_Legend.Reset();
2052  return;
2053  }
2054  struct SLegendData
2055  {
2056  string annot;
2057  string label;
2058  CRgbaColor color;
2059  CHistParams* params;
2060  };
2061  CRef<CHistParams> params = GetHistParams();
2062  _ASSERT(params);
2063 
2065  IRender& gl = GetGl();
2066 
2067  TModelRange vis_r = m_Context->IntersectVisible(this);
2068 
2069  CRgbaColor color_max = params->m_SmearColorMax;
2070  CRgbaColor color_min = params->m_SmearColorMin;
2071 
2072  TModelUnit legend_item_span = 0;
2073  vector<SLegendData> legend_fields;
2074  for (int bin = 0; bin < m_NumBins; ++bin) {
2075  SLegendData data;
2076  data.annot = m_AnnotName;
2077  data.params = params.GetPointer();
2078  data.label = NStr::NumericToString(bin * m_BinSize + 1);
2079  data.label += "..";
2080  if (bin + 1 == m_NumBins)
2082  else
2083  data.label += NStr::NumericToString((bin + 1) * m_BinSize);
2084  data.color = CRgbaColor::Interpolate(color_max, color_min, float(bin) / (m_NumBins - 1));
2085 
2086  legend_item_span = max((TModelUnit)gl.TextWidth(&font, data.label.c_str()), legend_item_span);
2087  legend_fields.push_back(data);
2088  }
2089  if (legend_fields.empty())
2090  return;
2091  legend_item_span += kLegendBarWidth + kLegendLabelGap + kLegenPadding;
2092 
2093  int view_width = m_Context->GetViewWidth();
2094  if (view_width == 0)
2095  view_width = m_Context->SeqToScreen(vis_r.GetLength());
2096  view_width -= 10;
2097 
2098  int num_cols = min((int)(view_width / legend_item_span), (int)legend_fields.size());
2099  if (num_cols == 0)
2100  return;
2101 
2102  if (!m_Legend) {
2103  CRef<CLayeredLayout> layered_layout(new CLayeredLayout);
2105  m_Legend->SetLayoutPolicy(&*layered_layout);
2107  m_Legend->SetParent(this);
2108  } else {
2109  m_Legend->Clear();
2110  }
2111 
2112  TModelUnit center = m_Context->SeqToScreen(vis_r.GetFrom() + vis_r.GetLength() / 2);
2113  int num_rows = ceil((float)legend_fields.size() / num_cols);
2114  TModelUnit row_height = gl.TextHeight(&font) + 2;
2115  for (int row = 0; row < num_rows; ++row) {
2116  size_t base_index = row * num_cols;
2117  // last row may have less columns
2118  if (base_index + num_cols >= legend_fields.size())
2119  num_cols = static_cast<int>(legend_fields.size() - base_index);
2120  int c = num_cols / 2;
2121  TModelUnit left = center;
2122  if (num_cols % 2 != 0)
2123  left -= legend_item_span / 2;
2124  for (int col = 0; col < c; ++col) {
2125  left -= 4;
2126  left -= legend_item_span;
2127  }
2128 
2129  for (int col = 0; col < num_cols; ++col) {
2131  (new CLegendItemGlyph(legend_fields[base_index + col].annot,
2132  legend_fields[base_index + col].label,
2134  legend_fields[base_index + col].color,
2135  legend_fields[base_index + col].params->m_LabelColor));
2136  g->SetTop(row * row_height + row * 4 + 2);
2137  g->SetHeight(row_height);
2138  g->SetWidth(m_Context->ScreenToSeq(legend_item_span));
2139  g->SetLeft(m_Context->ScreenToSeq(left));
2140  g->SetConfig(*m_gConfig);
2141  // g->SetHost(this);
2142  m_Legend->PushBack(&*g);
2143 
2144  left += 4;
2145  left += legend_item_span;
2146  }
2147  }
2148 
2150  m_Legend->SetLeft(GetLeft());
2152  m_Legend->SetHeight(row_height * num_rows + num_rows * 4);
2154 
2155 }
2156 
2157 
2159 {
2160  CRef<CHistParams> params = GetHistParams();
2161  SetHeight(params->m_Height);
2162  TSeqRange range = GetRange();
2163  SetWidth(range.GetLength());
2164  SetLeft(range.GetFrom());
2165  x_UpdateLegend();
2166 }
2167 
2169 {
2170  TMap::runlen_iterator seg_it = densityMap.RunLenBegin();
2171 
2172  mean = TDataType(0);
2173  TDataType variance = TDataType(0);
2174  TDataType samples = (TDataType)(densityMap.GetStop()-densityMap.GetStart()) + 1;
2175 
2176  // First find all the 0 entries since we do not include them in our calculations of mean and
2177  // standard deviation (Of course there are different datasources so in some cases 0 may
2178  // be a legitamite value, but I think that's not always the case)
2179  for (; seg_it; seg_it.Advance()) {
2180  TDataType value = seg_it.GetValue();
2181  if (value == TDataType(0) || value == densityMap.GetDefVal()) {
2182  TSeqPos f = seg_it.GetSeqPosition();
2183  TSeqPos t = seg_it.GetSeqRunEndPosition();
2184 
2185  samples -= TDataType(t-f);
2186  continue;
2187  }
2188  }
2189 
2190  // Compute the mean, ignoring 0-values.
2191  TMap::runlen_iterator seg_it2 = densityMap.RunLenBegin();
2192  for (; seg_it2; seg_it2.Advance()) {
2193  TDataType value = seg_it2.GetValue();
2194  if (value == TDataType(0) || value == densityMap.GetDefVal()) {
2195  continue;
2196  }
2197 
2198  TSeqPos f = seg_it2.GetSeqPosition();
2199  TSeqPos t = seg_it2.GetSeqRunEndPosition();
2200  mean += (TDataType(t-f)*value)/samples;
2201  }
2202 
2203  // Compute the variance (avg. distance squared from the mean)
2204  TMap::runlen_iterator seg_it3 = densityMap.RunLenBegin();
2205  for (; seg_it3; seg_it3.Advance()) {
2206  TDataType value = seg_it3.GetValue();
2207  if (value == TDataType(0) || value == densityMap.GetDefVal())
2208  continue;
2209  TSeqPos f = seg_it3.GetSeqPosition();
2210  TSeqPos t = seg_it3.GetSeqRunEndPosition();
2211  TDataType delta = value-mean;
2212  variance += TModelUnit(t-f)*(delta*delta)/samples;
2213  }
2214 
2215  // Compute standard deviation as square root of the variance
2216  variance = sqrt(variance);
2217 
2218 #ifdef ATTRIB_MENU_SUPPORT
2219  m_SD = variance;
2220 #endif
2221 
2222  return variance;
2223 }
2224 
2225 
2227 {
2228  TMap::runlen_iterator seg_it = densityMap.RunLenBegin();
2229 
2230  TDataType max_value = TDataType(0);
2231  bool outlier=false;
2232 
2233  // Find the largest value below m_AxisMax IF there is at least one value above m_AxisMax. This
2234  // lets us cut the visible range of the graph to the level of the highest value that is not an outlier.
2235  for (; seg_it; seg_it.Advance()) {
2236  TDataType value = seg_it.GetValue();
2237  if (value == densityMap.GetDefVal())
2238  continue;
2239  if (value <= m_AxisMax)
2240  max_value = std::max(max_value, value);
2241  else
2242  outlier = true;
2243  }
2244 
2245  if (outlier)
2246  return max_value;
2247 
2248  return m_AxisMax;
2249 }
2250 
2252 {
2253  TMap::runlen_iterator seg_it = densityMap.RunLenBegin();
2254 
2255  TDataType min_value = m_AxisMin; //TDataType(0);
2256  bool outlier=false;
2257 
2258  // Find the largest value below m_AxisMax IF there is at least one value above m_AxisMax. This
2259  // lets us cut the visible range of the graph to the level of the highest value that is not an outlier.
2260  for (; seg_it; seg_it.Advance()) {
2261  TDataType value = seg_it.GetValue();
2262  if (value == densityMap.GetDefVal())
2263  continue;
2264  if (value <= m_AxisMin)
2266  else
2267  outlier = true;
2268  }
2269 
2270  if (outlier)
2271  return min_value;
2272 
2273  return m_AxisMin;
2274 }
2275 
2277 {
2278  if (!x_HasLegend())
2279  return;
2280 
2281  // draw smear bar
2282  CRef<CHistParams> params = GetHistParams();
2283  CRgbaColor color_max = params->m_SmearColorMax;
2284  CRgbaColor color_min = params->m_SmearColorMin;
2285 
2286  for (int bin = 0; bin < m_NumBins; ++bin) {
2287  CRef<CLegendItem> legend_item(new CLegendItem);
2288  legend_item->SetId("");
2289 
2290  string label = NStr::NumericToString(bin * m_BinSize + 1);
2291  label += "..";
2292  if (bin + 1 == m_NumBins)
2294  else
2295  label += NStr::NumericToString((bin + 1) * m_BinSize);
2296  legend_item->SetLabel(label);
2297  auto color = CRgbaColor::Interpolate(color_max, color_min, float(bin) / (m_NumBins - 1));
2298  legend_item->SetColor(color.ToString());
2299  legend.push_back(legend_item);
2300  }
2301 }
2302 
2304 {
2305  return m_NumBins > 1;
2306 }
2307 
User-defined methods of the data storage class.
T round(const T &v)
static CAttribMenu & GetInstance()
Return a static instance of CAttribMenu.
Definition: attrib_menu.cpp:50
class CAttribMenuItem
CAttribMenu * FindMenu(const std::string &name)
CAttribIntMenuItem * AddInt(const std::string &name, int *user_value=NULL, int initial_value=50, int min_value=0, int max_value=100, int stepsize=1)
CAttribFloatMenuItem * AddFloatReadOnly(const std::string &name, float *user_value)
Add entries to the menu which display the users value but do not update it.
CAttribMenu * AddSubMenu(const std::string &name, void *user_value=NULL)
Convienance funcions to add new menu elements or submenus.
Run iterator. iterate through runs of equal values in the bins.
class CDensityMap generates a low-resolution view of a set of features.
virtual void SetRegistryPath(const string &path)
Definition: dialog.cpp:59
CConfigurableItems - a static list of items that can be configured.
string GetStoragekey(int type, int subtype) const
Get the key used to store this type of feature.
string GetDescription(int type, int subtype) const
Get the displayable description of this type of feature.
CGlAttrGuard - guard class for restoring OpenGL attributes.
Definition: glutils.hpp:130
class CGlPane
Definition: glpane.hpp:62
string m_Descr
description that can be used as label or tooltip
@ fNoTooltip
do not request and show tooltip
@ fZoomOnDblClick
Zoom on Double click.
@ fNoPin
tooltip is not pinnable
@ fNoHighlight
no highlighting on mouse over
@ fComment
render a label/comment on client side
@ fNoSelection
the object can't be selected
@ fTooltipEmbedded
tooltip embedded
string m_ID
area identifier
int m_Flags
area flags, will need to replace m_Type
bool m_PositiveStrand
the default is true
void SetConfig(CRef< CHistParams > config)
bool CreateX(wxWindow *parent, wxWindowID id=ID_CHISTCONFIGDLG, const wxString &caption=_("Graph Rendering Options"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL)
void SetHistName(const string &title)
CRef< CHistParams > GetConfig() const
void SetConfigName(const string &name)
void AddSettings(const string &name, CRef< CHistParams > hist_params)
Add a new settings for a given name.
bool IsTempSettings(const string &name) const
Check if there is settings for a given name.
File Description:
CRgbaColor m_fgNegColor
CRgbaColor m_SmearColorMin
CRgbaColor m_LabelColor
EScale m_StoredScale
stored scale of the underlying data (e.g. as reported by TMS)
CRgbaColor m_OutlierColor
CRgbaColor m_RulerColor
EScale m_Scale
requested scale
TModelUnit m_Height
CRgbaColor m_bgColor
CRgbaColor m_fgColor
CRange< float > m_ValueRange
static const string & ScaleValueToName(CHistParams::EScale scale)
CRgbaColor m_SmearColorMax
CHistogramData(TSeqPos start=0, TSeqPos stop=0, double window=1, accum_functor *func=NULL, float def=0)
CHistogramData & operator=(const CHistogramData &map)
TModelPoint GetFirstPoint() const
TModelPoint GetLastPoint() const
TModelPoint m_FirstPoint
EInterpolationMethod m_InterpolationMethod
void InitDataPoints(const TModelPoint &first_point, const TModelPoint &last_point)
TModelPoint m_LastPoint
TDataPoints m_DataPoints
EInterpolationMethod GetInterpolationMethod() const
const TDataPoints & GetDataPoints() const
TModelPoint GetDataPoint(size_t idx) const
const string & GetAnnotName() const
TDataType x_MapValue(TDataType val, CRgbaColor **color=0, bool *outlier=0) const
void x_DrawDataPoints(const TMap &densityMap) const
CConstRef< CSeqGraphicConfig > m_gConfig
TDataType GetAxisMin() const
virtual void x_Draw() const
The default renderer for this layout object.
void x_DrawLogRuler(bool negative) const
objects::CSeqFeatData::E_Choice GetFeatType() const
TDataType GetMin() const
bool isRmtBased() const
const string & GetDesc() const
void x_GetLabel(string &label) const
void SetAnnotName(const string &name)
virtual bool IsClickable() const
Query if this glyph is clickable.
void x_DrawGraph(TMaps::const_iterator &map_iter) const
virtual void GetTooltip(const TModelPoint &, ITooltipFormatter &tt, string &t_title) const
Get the tooltip if available.
string m_AnnotName
Key for accessing histogram settings.
const string & GetTitle() const
virtual bool NeedTooltip(const TModelPoint &p, ITooltipFormatter &tt, string &t_title) const
Check if need to show tooltip.
bool x_HasLegend() const
void x_DrawGraphMap(TMaps::const_iterator &map_iter, const CHistParams &config) const
void x_DrawHeatMap(TMaps::const_iterator &map_iter, const CHistParams &config) const
void x_DrawSmoothCurve(vector< TModelPoint > &points) const
virtual void GetHTMLActiveAreas(TAreaVector *p_areas) const
Get html active areas.
TDataType GetAxisMax() const
Get the axis limits (max/min).
virtual bool OnLeftDblClick(const TModelPoint &)
struct { TSeqRange range SOutlier
IGlyphDialogHost * m_DlgHost
TDataType GetMax() const
Get the actually density max/min values.
void x_DrawLinearRuler(bool negative) const
CRef< CLayoutGroup > m_Legend
virtual TSeqRange GetRange(void) const
get the total range of this object.
ERenderingMode m_Mode
objects::CSeqFeatData::ESubtype GetFeatSubtype() const
TDataType x_HighestValueBelowMax(const TMap &densityMap) const
virtual void x_UpdateBoundingBox()
Update the bounding box assuming children's sizes are fixed if any.
void GetLegend(objects::CTrackConfig::TLegend &legend) const
CHistogramGlyph(const TMap &map, objects::CSeqFeatData::ESubtype subtype, const string &title="")
vector< SOutlier > m_Outliers
void DrawGrid(bool include_background) const
TDataType x_ComputeDeviation(const TMap &densityMap, TDataType &mean) const
TModelPoint x_PointToWorld(TModelPoint p) const
virtual bool IsCoverageGraph() const
CRef< CHistParams > GetHistParams() const
objects::CSeqFeatData::ESubtype m_Subtype
TDataType x_LowesetValueBelowMin(const TMap &densityMap) const
void SetConfig(const CSeqGraphicConfig &config)
CLayeredLayout is a standard 2D layout policy.
CLayoutGroup is a container of CSeqGlyphs (layout objects).
void SetLayoutPolicy(ILayoutPolicy *policy)
Set policy on how to deploy the layout of its children.
void PushBack(CSeqGlyph *obj)
Append a layout object to the end.
virtual void GetHTMLActiveAreas(TAreaVector *p_areas) const
Get html active areas.
CLegendItem –.
Definition: LegendItem.hpp:66
static string GetHistogramSignature(const objects::CSeq_loc &loc, EObjectType obj_type, objects::CScope *scope, const string &title, const string &data_source="", int subtype=0)
CRenderingContext offers the basic context and utility methods for rendering layout objects in featur...
void TextOut(const CGlTextureFont *font, const char *text, TModelUnit x, TModelUnit y, bool center, bool adjust_flip=true) const
CRef< CSGSequenceDS > GetSeqDS() const
CGlPane * GetGlPane()
inline method implementations
const TModelUnit & GetOffset() const
TModelRange IntersectVisible(const CSeqGlyph *obj) const
TVPUnit SeqToScreenX(const TModelUnit &size) const
void DrawLine(TModelUnit x1, TModelUnit y1, TModelUnit x2, TModelUnit y2) 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 ScreenToSeq(const TModelUnit &size) const
convert from screen pixels to sequence positions
bool IsFlippedStrand() const
TSeqPos GetViewWidth() const
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
static bool IsBackgroundJob()
TSeqPos GetSequenceLength() const
objects::CBioseq_Handle GetBioseqHandle(void) const
Get the underlying bioseq handle.
static E_Choice GetTypeFromSubtype(ESubtype subtype)
static const CFeatList * GetFeatList()
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 x_OnLayoutChanged()
update the layout.
Definition: seq_glyph.cpp:353
virtual void SetHeight(TModelUnit h)
Definition: seq_glyph.hpp:650
const CRenderingContext * GetRenderingContext() const
Get the rendering context.
Definition: seq_glyph.hpp:690
virtual TModelUnit GetRight() const
Definition: seq_glyph.hpp:603
void SetParent(CSeqGlyph *p)
Definition: seq_glyph.hpp:670
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 void SetTop(TModelUnit b)
Definition: seq_glyph.hpp:658
void Draw() const
render the layout.
Definition: seq_glyph.cpp:92
void x_Local2World(TModelPoint &p) const
Transform the coordiantes from local coord. to world coord.
Definition: seq_glyph.hpp:726
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
void SetRenderingContext(CRenderingContext *context)
Set the rendering context.
Definition: seq_glyph.hpp:684
CRef< CHistParamsManager > GetHistParamsManager() const
Get histogram config manager.
bool GetCgiMode() const
virtual void PostDialogShow()=0
Post-processing after showing a dialog.
virtual void PreDialogShow()=0
Prepare for showing a dialog.
primitive interface to arrange tabular data in the tooltips
Definition: tooltip.hpp:55
size_type size() const
Definition: map.hpp:148
container_type::const_iterator const_iterator
Definition: map.hpp:53
const_iterator begin() const
Definition: map.hpp:151
iterator_bool insert(const value_type &val)
Definition: map.hpp:165
bool empty() const
Definition: map.hpp:149
Definition: map.hpp:338
static const Colors colors
Definition: cn3d_colors.cpp:50
CS_CONTEXT * ctx
Definition: t0006.c:12
#define false
Definition: bool.h:36
static char precision
Definition: genparams.c:28
static FILE * f
Definition: readconf.c:23
char data[12]
Definition: iconv.c:80
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
static bool IsCoverageAnnotName(const string &annot_name)
Definition: utils.hpp:549
static bool IsUnnamed(const string &annot)
check if a given annotation is a unnamed annotation.
Definition: utils.hpp:528
static bool isRmtAnnotName(const string &sAnnotname)
check if a given annotation was created by a remote file pipeline
Definition: utils.cpp:814
GLdouble TModelUnit
Definition: gltypes.hpp:48
void SetRight(T right)
Definition: glrect.hpp:114
virtual void Scalef(GLfloat x, GLfloat y, GLfloat z)=0
T X() const
Definition: glpoint.hpp:59
T Height() const
Definition: glrect.hpp:90
void SetViewport(const TVPRect &R)
Definition: glpane.cpp:96
virtual void Translatef(GLfloat x, GLfloat y, GLfloat z)=0
virtual void Enable(GLenum glstate)=0
bool OpenOrtho()
Definition: glpane.hpp:427
void Init()
Definition: glrect.hpp:62
virtual void Begin(GLenum mode)=0
Start rendering.
void SetBottom(T bottom)
Definition: glrect.hpp:113
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
bool OpenPixels()
Definition: glpane.hpp:432
TVPUnit ProjectX(TModelUnit m_x) const
Definition: glpane.cpp:661
IRender & GetGl()
convenience function for getting current render manager
void Vertex2d(GLdouble x, GLdouble y)
Definition: irender.hpp:185
T Right() const
Definition: glrect.hpp:83
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
virtual TModelUnit TextHeight(const CGlTextureFont *font) const =0
virtual TModelUnit TextWidth(const CGlTextureFont *font, const char *text) const =0
virtual void PopAttrib()=0
virtual void PushAttrib(GLbitfield mask)=0
virtual void LoadIdentity()=0
virtual void PopMatrix()=0
virtual void ShadeModel(GLenum mode)=0
Set shade model for default lighting: glShadeModel(GL_FLAT or GL_SMOOTH)
T Y() const
Definition: glpoint.hpp:60
bool PtInRect(T x, T y) const
Definition: glrect.hpp:154
virtual void End()=0
Finish rendering (create buffer and send to renderer)
virtual ERenderTarget GetApi()=0
void Close(void)
Definition: glpane.cpp:178
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
void Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
Definition: irender.hpp:97
virtual TModelUnit GetMetric(EMetric metric, const char *text=NULL, int len=-1) const
void SetLeft(T left)
Definition: glrect.hpp:112
void Vertex2f(GLfloat x, GLfloat y)
Definition: irender.hpp:182
virtual void Disable(GLenum glstate)=0
glDisable()
virtual void LineWidth(GLfloat w)=0
Set line width for drawing: glLineWidth()
CGlPoint< TModelUnit > TModelPoint
Definition: gltypes.hpp:51
virtual void ColorC(const CRgbaColor &c)=0
Set current color (glColor{3,4}{f,d}{v,})
void SetTop(T top)
Definition: glrect.hpp:115
virtual void PushMatrix()=0
@ eRenderSVG
Definition: glstate.hpp:61
@ eMetric_FullCharHeight
Definition: glfont.hpp:80
void SetMin(const float &min)
TSeqPos GetSeqPosition() const
virtual void AddRow(const string &sContents="", unsigned colspan=2)=0
add a row with a cell, spanning across all columns
float GetBlue(void) const
Definition: rgba_color.hpp:333
float GetGreen(void) const
Definition: rgba_color.hpp:327
size_t GetBins() const
void SetAlpha(float r)
Definition: rgba_color.cpp:287
void SetMax(const float &max)
static CIRef< ITooltipFormatter > CreateTooltipFormatter(ETooltipFormatters)
factory for requested tooltip formatter creation
Definition: tooltip.cpp:40
runlen_iterator RunLenBegin() const
TSeqPos GetSeqRunEndPosition() const
float GetMin() const
float GetAlpha(void) const
Definition: rgba_color.hpp:339
position_type GetRunLength() const
CDensityMap< CntType > & operator=(const CDensityMap< CntType > &map)
TSeqPos GetStop() const
void Lighten(float scale)
Definition: rgba_color.cpp:463
float GetDefVal() const
static CRgbaColor Interpolate(const CRgbaColor &color1, const CRgbaColor &color2, float alpha)
Interpolate two colors.
Definition: rgba_color.cpp:444
CntType GetValue() const
float GetMax() const
position_type GetPosition() const
TSeqPos GetStart() const
float GetRed(void) const
Get specific channels in floating point values.
Definition: rgba_color.hpp:321
@ eTooltipFormatter_CSSTable
generated table is CSS based, generated NCBI URLs are paths (recommended for SViewer)
Definition: tooltip.hpp:59
void SetInt(TInt &v)
Definition: Seq_loc.hpp:983
bool ExtractZoomLevel(const string &full_name, string *acc_ptr, int *zoom_level_ptr)
Extract optional zoom level suffix from named annotation string.
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:1439
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
bool IsNull(void) const THROWS_NONE
Check if pointer is null – same effect as Empty().
Definition: ncbiobj.hpp:735
position_type GetLength(void) const
Definition: range.hpp:158
static position_type GetEmptyFrom(void)
Definition: range.hpp:290
static position_type GetEmptyTo(void)
Definition: range.hpp:298
CRange< TSeqPos > TSeqRange
typedefs for sequence ranges
Definition: range.hpp:419
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5181
static string & Replace(const string &src, const string &search, const string &replace, string &dst, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3305
#define NcbiEmptyString
Definition: ncbistr.hpp:122
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5406
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
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
list< CRef< CLegendItem > > TLegend
void SetTo(TTo value)
Assign a value to To data member.
void SetId(TId &value)
Assign a value to Id data member.
void SetFrom(TFrom value)
Assign a value to From data member.
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
USING_SCOPE(objects)
static const float kDataPointRadius
static const string kCoverageLabel
static bool IsOutlierTooltips(CRenderingContext &ctx)
static const int kLegendBarWidth
static const int kRulerLebelsMinDistance
#define M_NCBI_E
static const int kLegendLabelGap
static const int kLegenPadding
n background color
int i
if(yy_accept[yy_current_state])
static void text(MDB_val *v)
Definition: mdb_dump.c:62
range(_Ty, _Ty) -> range< _Ty >
constexpr bool empty(list< Ts... >) noexcept
double value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:228
const struct ncbi::grid::netcache::search::fields::SIZE size
#define min_value(a, b)
Definition: ncbi_c_log.c:140
#define fabs(v)
Definition: ncbi_dispd.c:46
EIPRangeType t
Definition: ncbi_localip.c:101
int toupper(Uchar c)
Definition: ncbictype.hpp:73
T max(T x_, T y_)
T log10(T x_)
T min(T x_, T y_)
T negative(T x_)
Int4 delta(size_t dimension_, const Int4 *score_)
#define FLT_EPSILON
Definition: stdtypes.cpp:214
#define row(bind, expected)
Definition: string_bind.c:73
void x_InitDenominator(double AxisMax, double &denom)
SLogScaleData(double AxisMax, double AxisMin, int height, CHistParams::EScale scale)
CHistParams::EScale m_Scale
double MapValue(double val)
TEMPLATE binary functor base struct.
Definition: density_map.hpp:59
Definition: type.c:6
#define _ASSERT
int g(Seg_Gsm *spe, Seq_Mtf *psm, Thd_Gsm *tdg)
Definition: thrddgri.c:44
Modified on Fri Sep 20 14:57:08 2024 by modify_doxy.py rev. 669887