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

Go to the SVN repository for this file.

1 /* $Id: feature_ds.cpp 47783 2024-08-23 19:29:57Z asztalos $
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: Liangshou Wu
27  *
28  */
29 #include <ncbi_pch.hpp>
30 
49 
52 
53 #include <objmgr/util/feature.hpp>
54 #include <objmgr/util/sequence.hpp>
58 
59 // for gene_by_loc reply
63 
65 
66 #include <serial/serial.hpp>
67 #include <connect/ncbi_types.h>
69 #include <serial/objistr.hpp>
70 
73 
74 // the maximal number of objects allowed to show without smearing
75 static const int kMaxObjNum = 250000;
76 
77 // the maximal number of children in parent/child situations dictated by approximation of screen size limits
78 static const size_t kMaxChildNum = 500;
79 // the zoom level that allows to show sequence
80 static const float kSeqZoomLevel = 0.125;
81 // unique group for 'unsorted' (no sorting is needed) features
82 static const char* kUnsortedGroupName = "--unsorted--";
83 
84 // create feature product mapping if scale (m_Window) is less than this value
85 static const float kMinScaleForMapping = 16.;
86 
87 
88 ///////////////////////////////////////////////////////////////////////////////
89 /// CSGFeatureJob: a job class for loading annotated features from a given
90 /// sequence and visible range.
91 ///////////////////////////////////////////////////////////////////////////////
92 class CSGFeatureJob : public CSGAnnotJob
93 {
94 public:
95  typedef pair<string, CLinkedFeature::TLinkedFeats> TSortedFeats;
96  typedef vector<TSortedFeats> TFeatGroups;
98 
100  {
101  float score;
103  };
104 
105  CSGFeatureJob(const string& desc, CBioseq_Handle handle,
106  const SAnnotSelector& sel, const TSeqRange& range,
107  TModelUnit window, TJobToken token);
108 
109  CSGFeatureJob(const string& desc, CBioseq_Handle handle,
110  const SAnnotSelector& sel, const TSeqRange& range,
111  TModelUnit window, int max_feat, ELinkedFeatDisplay LinkedFeatDisplay,
112  TJobToken token, ICoordMapper* mapper = NULL);
113 
114  void SetFilter(const string& filter)
115  { m_Filter = filter; }
116 
117  void SetSortBy(const string& sortby);
118 
119  void SetBigBedCacheKey(const string& cache_key)
120  {
121  m_BigBedCacheKey = cache_key;
122  }
123 
124  void SetVcfCacheKey(const string& cache_key)
125  {
126  m_VcfCacheKey = cache_key;
127  }
128 
129 
130  static void GetAnnotNames(const CBioseq_Handle& handle,
132 
133  static void GetAnnotNames_var(const CBioseq_Handle& handle,
135 
136 
137 protected:
138  virtual EJobState x_Execute();
139 
140  /// @name feature glyph creators.
141  /// Using different function names to get by hide-by-name semantics.
142  /// Maybe should consider using 'using scope' directive in the
143  /// derived class.
144  /// @{
145  /// shared creator.
147  CSeqGlyph* parent_glyph = NULL,
148  const char* label_prefix = NULL);
149 
150  /// overridable creator.
152  const CMappedFeat& feat, const CSeq_loc& loc,
153  const char* label_prefix = NULL);
154  /// @}
155 
156  vector<CRef<CSeqGlyph>> x_CreateCrossOriginGlyphs(const CMappedFeat& feat, CSeqGlyph* parent_glyph = nullptr,
157  const char* label_prefix = nullptr);
158 
159  vector<CRef<CSeqGlyph>> x_CreateAndFilterCrossOriginGlyphs(const CMappedFeat& feat, const TSeqRange& range, CSeqGlyph* parent_glyph = nullptr,
160  const char* label_prefix = nullptr);
161 
163  const CSeq_loc& loc);
164 
166  CLinkedFeature::TLinkedFeats& features, CLayoutGroup* group, int Level);
167 
169  CSeqGlyph::TObjects& objs);
170 
171  void x_CalcIntervals(CFeatGlyph& feat);
172 
174  CSGJobResult* result, const string& title);
175 
177  CSGJobResult* result, const string& title);
178 
180  int level, const string& title);
181 
183  CSGJobResult* result, const string& title);
184 
187  CFeatureFilter& filter);
188 
190  TFeatGroups& feat_groups);
191 
193  TFeatGroupMap& group_map);
194 
195  void x_GetLinkedFeatures(CFeat_CI& feature_iter, CLinkedFeature::TLinkedFeats& features);
198 
199  bool x_ProcessCachedBigBed();
201 
202 
203 protected:
204  TModelUnit m_Window; ///< current window for smear bars
205  /// the maximum number of features allowed.
206  /// -2: pack all features into one smear line
207  /// -1: theoretically unlimited, practically there is one (kMaxObjNum)
208  /// -0: pack all features into a histogram
209  /// >0: any limit set from a user
211 
212  /// controls creation of parent or child features
214 
215  string m_Filter;
217 
219 
222 
223 };
224 
225 
226 ///////////////////////////////////////////////////////////////////////////////
227 /// CGeneModelFeatJob: a job class for loading annotated main features,
228 /// including genes, RNAs, CDSs and exons from a given sequence and a given
229 /// visible range.
230 ///////////////////////////////////////////////////////////////////////////////
232 {
233 public:
236  eFilter_dbref_all = 0, ///< any dbref
237  eFilter_dbref, ///< one specific dbref
238  eFilter_CCDS, ///< genes with Consensus CDS
242  };
243 
244  typedef int TFilterType;
245 
246  CGeneModelFeatJob(const string& desc,
247  CBioseq_Handle handle,
248  const SAnnotSelector& lm_feat_sel,
249  const SAnnotSelector& m_feat_sel,
250  TJobToken lm_token, TJobToken main_token,
251  bool landmark_feat,
252  const TSeqRange& range, TModelUnit window,
253  const CGeneModelConfig& conf,
254  ICoordMapper* mapper);
255 
256  static vector<string> GetFilters(const CBioseq_Handle& handle,
257  const TSeqRange& range, SAnnotSelector& sel, const string& filter);
258 
259 protected:
260  virtual EJobState x_Execute();
261 
263  const CMappedFeat& feat, const CSeq_loc& loc,
264  const char* label_prefix = NULL);
265 
266 private:
268  CRef<CSeqGlyph>& hist_obj, CSeqGlyph::TObjects& comment_objs);
269 
270  /// Link features into a hierarchical list. This function will transform a
271  /// linear, feature-order-sorted list of CLayoutFeat objects into a
272  /// hierarchically arranged list in which genes are linked to mRNAs, mRNAs
273  /// to CDSs, etc.
275 
276  /// create features when there is a filter set up.
278 
279  /// Check if transcript passes Config filters
280  bool x_IsTranscriptAcceptable(const CLinkedFeature& feat);
281 
282  static TFilterType x_FilterStrToValue(const string& filter);
283 
284  static bool x_IsDbref(const string& db, const CSeq_feat& feat)
285  {
286  if (feat.IsSetDbxref()) {
287  ITERATE (CSeq_feat::TDbxref, iter, feat.GetDbxref()) {
288  if (NStr::EqualNocase(db, (*iter)->GetDb())) {
289  return true;
290  }
291  }
292  }
293  return false;
294  }
295 
296  static bool x_IsDbref(const string& db, const CLinkedFeature& linked_feat) {
297  const CSeq_feat& feat = linked_feat.GetFeature();
298  if (x_IsDbref(db, feat)) {
299  return true;
300  }
301 
302  ITERATE (CLinkedFeature::TLinkedFeats, iter, linked_feat.GetChildren()) {
303  if (x_IsDbref(db, **iter)) {
304  return true;
305  }
306  }
307 
308  return false;
309  }
310 
311  static bool x_IsCCDS(const CLinkedFeature& linked_feat) {
312  const CSeq_feat& feat = linked_feat.GetFeature();
313  if (feat.GetData().IsGene()) {
314  ITERATE (CLinkedFeature::TLinkedFeats, iter, linked_feat.GetChildren()) {
315  const CSeq_feat& c_feat = (*iter)->GetFeature();
316  if (c_feat.GetData().IsRna()) {
317  ITERATE (CLinkedFeature::TLinkedFeats, c_iter, (*iter)->GetChildren()) {
318  if (x_IsDbref("CCDS", (*c_iter)->GetFeature())) {
319  return true;
320  }
321  }
322  } else if (c_feat.GetData().IsCdregion()) {
323  if (x_IsDbref("CCDS", c_feat)) {
324  return true;
325  }
326  }
327  }
328  }
329  return false;
330  }
331 
332  static bool x_IsPseudoGene(const CSeq_feat& feat)
333  {
334  return (feat.IsSetPseudo() && feat.GetPseudo());
335  }
336 
337  static bool x_IsncRNA(const CLinkedFeature& linked_feat) {
338  const CSeq_feat& feat = linked_feat.GetFeature();
339  bool has_rna = false;
340  bool has_cds = false;
341  if (feat.GetData().IsGene()) {
342  ITERATE (CLinkedFeature::TLinkedFeats, iter, linked_feat.GetChildren()) {
343  const CSeq_feat& c_feat = (*iter)->GetFeature();
344  if (c_feat.GetData().IsRna()) {
345  has_rna = true;
346  if (!(*iter)->GetChildren().empty()) {
347  has_cds = true;
348  }
349  }
350  }
351  } else if (feat.GetData().IsRna()) {
352  has_rna = true;
353  if (!linked_feat.GetChildren().empty()) {
354  has_cds = true;
355  }
356  }
357  return has_rna && !has_cds;
358  }
359 
360  static bool x_IsnpcGene(const CLinkedFeature& linked_feat) {
361  const CSeq_feat& feat = linked_feat.GetFeature();
362  if (feat.GetData().IsGene()) {
363  ITERATE (CLinkedFeature::TLinkedFeats, iter, linked_feat.GetChildren()) {
364  const CSeq_feat& c_feat = (*iter)->GetFeature();
365  if ( (c_feat.GetData().IsRna() && !(*iter)->GetChildren().empty()) ||
366  c_feat.GetData().IsCdregion()) {
367  return false;
368  }
369  }
370  }
371  return true;
372  }
373 
374 private:
375  SAnnotSelector m_MainFeatSel; ///< annotation selector for all main features.
376  TJobToken m_MainFeatToken; ///< Job token for loading main features.
377  bool m_LandmarkFeats; ///< is overview mode?
379 };
380 
381 
382 ///////////////////////////////////////////////////////////////////////////////
383 /// CBatchFeatJob: a job class for loading annotated features from a given
384 /// a set of sequences within the corresponding visible ranges.
385 ///////////////////////////////////////////////////////////////////////////////
387 {
388 public:
389  CBatchFeatJob(const string& desc, CBioseq_Handle handle,
390  const TSeqRange& range, TModelUnit window, TJobToken token,
391  const TFeatBatchJobRequests& requests);
392 
393 protected:
394  virtual EJobState x_Execute();
395 
396 private:
398  const SAnnotSelector& sel);
399 
400 private:
402 };
403 
404 
405 ///////////////////////////////////////////////////////////////////////////////
406 /// CSGCalcFeatHistJob
407 ///////////////////////////////////////////////////////////////////////////////
409 {
410 public:
411  CSGCalcFeatHistJob(const string& desc, const CSeqGlyph::TObjects& objs,
412  const TSeqRange& range, TModelUnit window, TJobToken token)
413  : CSeqGraphicJob(desc)
414  , m_Objects(objs)
415  , m_Range(range)
416  , m_Window(window)
417  {
418  SetToken(token);
419  }
420 
421 protected:
422  virtual EJobState x_Execute();
423 
424 private:
426  CDensityMap<float>& the_map);
427 
428 private:
430  TSeqRange m_Range; ///< target range
431  TModelUnit m_Window; ///< current window for smear bars
432 };
433 
434 
435 ///////////////////////////////////////////////////////////////////////////////
436 /// CSGFeatureDS
437 ///////////////////////////////////////////////////////////////////////////////
439  : CSGGenBankDS(scope, id)
440 {}
441 
443  const TSeqRange& range, TModelUnit window,
444  TJobToken token, int max_feat,
445  ELinkedFeatDisplay LinkedFeat,
446  const string& extra_filter)
447 {
450  new CSGFeatureJob("Feature", m_Handle, sel, range, window,
451  max_feat, LinkedFeat,
452  token, m_Mapper));
453  job->SetGraphLevel(CGraphUtils::GetNearestLevel(m_GraphLevels, window));
454  string filter = m_Filter;
455  if (!extra_filter.empty()) {
456  if (!filter.empty()) filter += " and ";
457  filter += extra_filter;
458  }
459  job->SetFilter(filter);
460  job->SetSortBy(m_SortBy);
461  if (IsBigBed())
462  job->SetBigBedCacheKey(m_GraphCacheKey);
463  else if (IsVcfTabix())
464  job->SetVcfCacheKey(m_GraphCacheKey);
465  x_LaunchJob(*job);
466 }
467 
468 
470  TModelUnit window,
471  TJobToken token,
472  const TFeatBatchJobRequests& requests)
473 {
474  //CSeqUtils::SetResolveDepth(sel, m_Adaptive, m_Depth);
476  "Feature", m_Handle, range, window, token, requests));
477  job->SetGraphLevel(CGraphUtils::GetNearestLevel(m_GraphLevels, window));
478  if (IsBigBed())
479  job->SetBigBedCacheKey(m_GraphCacheKey);
480  else if (IsVcfTabix())
481  job->SetVcfCacheKey(m_GraphCacheKey);
482 
483  // no progress report
484  x_LaunchJob(*job, -1);
485 }
486 
487 
489  SAnnotSelector& lm_feat_sel,
490  SAnnotSelector& m_feat_sel,
491  TJobToken lm_token, TJobToken main_token,
492  bool landmark_feat, const TSeqRange& range, TModelUnit window,
493  const CRef<CGeneModelConfig>& conf)
494 {
498  "Feature", m_Handle, lm_feat_sel, m_feat_sel, lm_token,
499  main_token, landmark_feat, range, window,
500  *conf, m_Mapper));
501  job->SetFilter(m_Filter);
502  job->SetSortBy(m_SortBy);
503  x_LaunchJob(*job);
504 }
505 
506 
507 
509  const TSeqRange& range,
510  TModelUnit window, TJobToken token)
511 {
513  "Calculate feature histogram", objs,
514  range, window, token));
515  x_LaunchJob(*job);
516 }
517 
518 
520  const TSeqRange& range,
521  TAnnotNameTitleMap& names) const
522 {
525 }
526 
527 
529  const TSeqRange& range,
530  TAnnotNameTitleMap& names) const
531 {
534 }
535 
536 
537 vector<string> CSGFeatureDS::GetFilters(const string& annot_name,
538  const TSeqRange& range) const
539 {
541  CSeqUtils::SetAnnot(sel, annot_name);
543 }
544 
545 
546 ///////////////////////////////////////////////////////////////////////////////
547 /// CSGFeatureDSType
548 ///////////////////////////////////////////////////////////////////////////////
549 
552 {
553  const CSeq_id& id = dynamic_cast<const CSeq_id&>(object.object.GetObject());
554 // cerr << "Creating DS for seq-id" << endl <<
555 // MSerial_AsnText << id << endl;
556  return new CSGFeatureDS(object.scope.GetObject(), id);
557 }
558 
559 
561 {
562  static string sid("seqgraphic_feature_ds_type");
563  return sid;
564 }
565 
566 
568 {
569  static string slabel("Graphical View Feature Data Source Type");
570  return slabel;
571 }
572 
573 
575 {
576  return false;
577 }
578 
579 //
580 //void CFeatFilter::x_AddToList(const string& type, bool shown)
581 //{
582 // TFeatTypeIdx idx = CCustomFeatureColor::eDefault;
583 // if (type == "cnv") {
584 // idx = CCustomFeatureColor::eCNV;
585 // } else if (type == "other") {
586 // idx = CCustomFeatureColor::eOther;
587 // } else if (type == "inversion") {
588 // idx = CCustomFeatureColor::eInversion;
589 // } else if (type == "loss") {
590 // idx = CCustomFeatureColor::eLoss;
591 // } else if (type == "gain") {
592 // idx = CCustomFeatureColor::eGain;
593 // } else if (type == "insertion") {
594 // idx = CCustomFeatureColor::eInsertion;
595 // } else if (type == "complex") {
596 // idx = CCustomFeatureColor::eComplex;
597 // } else if (type == "unknown") {
598 // idx = CCustomFeatureColor::eUnknown;
599 // } else if (type == "loh") {
600 // idx = CCustomFeatureColor::eLOH;
601 // } else if (type == "everted") {
602 // idx = CCustomFeatureColor::eEverted;
603 // } else if (type == "translocation") {
604 // idx = CCustomFeatureColor::eTranschr;
605 // } else if (type == "upd") {
606 // idx = CCustomFeatureColor::eUPD;
607 // }
608 // if (idx != CCustomFeatureColor::eDefault) {
609 // if (shown) {
610 // m_ShowList.insert(idx);
611 // m_HideList.clear();
612 // } else {
613 // m_HideList.insert(idx);
614 // m_ShowList.clear();
615 // }
616 // }
617 //}
618 
619 
620 ///////////////////////////////////////////////////////////////////////////////
621 /// CSGFeatureJob implementation
622 ///////////////////////////////////////////////////////////////////////////////
624 {
626  const CSGFeatureJob::SLandmarkFeat& f2) const
627  {
628  return f1.score > f2.score;
629  }
630 };
631 
633 {
635  const CSGFeatureJob::SLandmarkFeat& f2) const
636  {
637  return f1.obj->LessBySeqPos(*f2.obj);
638  }
639 };
640 
641 
642 CSGFeatureJob::CSGFeatureJob(const string& desc, CBioseq_Handle handle,
643  const SAnnotSelector& sel,
644  const TSeqRange& range, TModelUnit window,
645  TJobToken token)
646  : CSGAnnotJob(desc, handle, sel, range)
647  , m_Window(window)
648  , m_FeatLimit(-1)
649  , m_LinkedFeat(ELinkedFeatDisplay::eLFD_Default)
650 {
651  SetToken(token);
652 }
653 
654 
655 CSGFeatureJob::CSGFeatureJob(const string& desc, CBioseq_Handle handle,
656  const SAnnotSelector& sel,
657  const TSeqRange& range, TModelUnit window,
658  int max_feat, ELinkedFeatDisplay LinkedFeatDisplay,
659  TJobToken token, ICoordMapper* mapper)
660  : CSGAnnotJob(desc, handle, sel, range)
661  , m_Window(window)
662  , m_FeatLimit(max_feat)
663  , m_LinkedFeat(LinkedFeatDisplay)
664  , m_Mapper(mapper)
665 {
666  SetToken(token);
667 }
668 
669 
670 void CSGFeatureJob::SetSortBy(const string& sortby)
671 {
672  if (sortby.empty()) {
673  m_Sorter.Reset(nullptr);
674  return;
675  }
676 
677  size_t found = sortby.find_first_of('|');
678  string sorter_type = NStr::TruncateSpaces(sortby.substr(0, found));
679  string sort_str = kEmptyStr;
680  if (found != string::npos) {
681  sort_str = sortby.substr(found + 1);
682  }
684  m_Sorter.Reset(new CCloneConcordancySorter(sort_str));
685  } else if (NStr::EqualNocase(sorter_type, CDbvarQualitySorter::GetID())) {
686  m_Sorter.Reset(new CDbvarQualitySorter(sort_str));
687  } else if (NStr::EqualNocase(sorter_type, CDbvarPilotSorter::GetID())) {
688  m_Sorter.Reset(new CDbvarPilotSorter(sort_str));
689  } else if (NStr::EqualNocase(sorter_type, CDbvarClinicalAsstSorter::GetID())) {
690  m_Sorter.Reset(new CDbvarClinicalAsstSorter(sort_str));
691  } else if (NStr::EqualNocase(sorter_type, CDbvarSamplesetTypeSorter::GetID())) {
693  } else if (NStr::EqualNocase(sorter_type, CDbvarValidationSorter::GetID())) {
694  m_Sorter.Reset(new CDbvarValidationSorter(sort_str));
695  } else if (NStr::EqualNocase(sorter_type, CGRCStatusSorter::GetID())) {
696  m_Sorter.Reset(new CGRCStatusSorter(sort_str));
697  } else if (NStr::EqualNocase(sorter_type, CFeatStrandSorter::GetID())) {
698  m_Sorter.Reset(new CFeatStrandSorter(sort_str));
699  }
700 }
701 
702 
704  const TSeqRange& range,
705  SAnnotSelector& sel,
707 {
708  sel.SetCollectNames();
709  CFeat_CI feat_iter(handle, range, sel);
710  ITERATE (CFeat_CI::TAnnotNames, iter, feat_iter.GetAnnotNames()) {
711  if (iter->IsNamed()) {
712  if (iter->GetName().find("@@") == string::npos) {
713  names.insert(TAnnotNameTitleMap::value_type(iter->GetName(), ""));
714  }
715  } else {
717  }
718  }
719 }
720 
721 
723  const TSeqRange& range,
724  SAnnotSelector& sel,
726 {
727  sel.SetCollectNames();
728  CFeat_CI feat_iter(handle, range, sel);
729  ITERATE (CFeat_CI::TAnnotNames, iter, feat_iter.GetAnnotNames()) {
730  if (iter->IsNamed()) {
731  if (iter->GetName().find("@@") == string::npos) {
732  names.insert(TAnnotNameTitleMap::value_type(iter->GetName(), ""));
733  }
734  } else {
736  }
737  }
738  /// TODO: look at the real feature for each annotaton to verify
739  /// it is really structural variants, not SNP.
740 }
741 
743 {
744 
745  features.clear();
746  for ( ; feature_iter; ++feature_iter) {
747  if (IsCanceled()) return;
748  const CMappedFeat& feat = *feature_iter;
749  features.emplace_back(new CLinkedFeature(feat));
750  }
751  // filtering features
752  if (!m_Filter.empty()) {
753  CFeatureFilter filter;
754  filter.Init(m_Filter);
755  if (filter.NeedFiltering()) {
756  if (IsCanceled()) return;
757  x_FilterFeature_recursive(features, filter);
758  }
759  }
760 }
761 
763 {
765  x_GetLinkedFeatures(feature_iter, features);
766  return x_LinkFeatures(features, objs);
767  }
768 
769 
770 
772 {
773  SetTaskName("Linking features...");
774  // linking features
775  if ( !CSeqUtils::LinkFeatures(features, feature::CFeatTree::eFeatId_always, this) ) {
776  return eCanceled;
777  }
778  TFeatGroups feat_groups;
779  x_SortFeatures(features, feat_groups);
780  SetTaskName("Creating feature glyphs...");
781  SetTaskCompleted(0);
782 
783  NON_CONST_ITERATE (TFeatGroups, grp_iter, feat_groups) {
784  if (IsCanceled()) {
785  return eCanceled;
786  }
787  CLinkedFeature::TLinkedFeats& curr_feats = grp_iter->second;
788  NON_CONST_ITERATE (CLinkedFeature::TLinkedFeats, iter, curr_feats) {
789  if(m_LinkedFeat == ELinkedFeatDisplay::eLFD_Hidden && !(*iter)->GetChildren().empty() ) {
790  (*iter)->GetChildren().clear();
791  }
792  }
794 
795  EJobState state = x_CreateFeature_Recursive(curr_feats, group.GetPointer(), 0);
796  if (state != eCompleted) {
797  return state;
798  }
799 
800  if (curr_feats.size() == group->GetChildrenNum()) {
801  // For most cases, we don't need the group container
802  // added earlier. Instead, take the children only.
803  if (grp_iter->first == kUnsortedGroupName) {
804  // Sorting features is not needed in this case.
805  // That means there should be only one group.
806  _ASSERT(feat_groups.size() == 1);
807  objs.swap(group->SetChildren());
808  } else {
809  // created a group with a title
810  CRef<CNamedGroup> named_group((new CNamedGroup(grp_iter->first)));
811  named_group->Set(group->SetChildren());
812  objs.emplace_back(named_group.GetPointer());
813  }
814  } else {
815  // There is one case we need to group the features:
816  // When all the features are linked together as one
817  // feature group with parent and child relationship.
818  // After x_CreateFeature_Recursive step, the parent
819  // feature and child feature(s) are put in one group
820  // which is this group container. We need it to hold
821  // them as a linked group.
822  if (grp_iter->first == kUnsortedGroupName) {
823  // Sorting features is not needed in this case.
824  // That means there should be only one group.
825  _ASSERT(feat_groups.size() == 1);
826  objs.emplace_back(group.GetPointer());
827  } else {
828  // created a group with a title
829  CRef<CNamedGroup> named_group((new CNamedGroup(grp_iter->first)));
830  named_group->PushBack(group);
831  objs.emplace_back(named_group.GetPointer());
832  }
833  }
834  }
835 
836  return eCompleted;
837 }
838 
839 
841 {
842  _ASSERT(m_Result);
843  if (!m_Result)
844  return false;
845  auto result = dynamic_cast<CSGJobResult*>(m_Result.GetPointer());
846  if (!result)
847  return false;
849  if (!data)
850  return false;
852  m_Range.GetTo(),
853  (float)m_Window,
855  data->GetData(the_map);
856 
858  annots = m_Sel.GetIncludedAnnotsNames();
859  for(const auto& annot : annots) {
860  if(annot.IsNamed()) {
861  result->m_Desc = annot.GetName();
862  break;
863  }
864  }
865  CRef<CHistogramGlyph> histogram(new CHistogramGlyph(the_map, result->m_Desc));
866  result->m_ExtraObj.Reset(histogram.GetPointer());
867  SetTaskCompleted(1);
868  return true;
869 }
870 
872 {
873  _ASSERT(m_Result);
874  if (!m_Result)
875  return false;
876  auto result = dynamic_cast<CSGJobResult*>(m_Result.GetPointer());
877  if (!result)
878  return false;
880  if (!data)
881  return false;
882  vector<TSeqRange> ranges;
883  data->GetData(m_Range, ranges);
885  m_Range.GetTo(),
886  (float)m_Window,
888  for (const auto& r : ranges) {
889  the_map.AddRange(r, 1);
890  }
891 
893  annots = m_Sel.GetIncludedAnnotsNames();
894  for(const auto& annot : annots) {
895  if(annot.IsNamed()) {
896  result->m_Desc = annot.GetName();
897  break;
898  }
899  }
900  CRef<CHistogramGlyph> histogram(new CHistogramGlyph(the_map, result->m_Desc));
901  result->m_ExtraObj.Reset(histogram.GetPointer());
902  SetTaskCompleted(1);
903  return true;
904 }
905 
906 
908 {
911 
913  m_Handle.GetRangeSeq_loc(m_Range.GetFrom(), m_Range.GetTo()) );
914 
915  SetTaskName("Loading features...");
916  SetTaskTotal(0);
917  SetTaskCompleted(0);
918 
919  try {
920  bool glyph_created = false;
921  if (!m_BigBedCacheKey.empty())
922  glyph_created = x_ProcessCachedBigBed();
923  else if (!m_VcfCacheKey.empty())
924  glyph_created = x_ProcessCachedVcfTabix();
925 
926  if (!glyph_created) {
927  bool has_coverage_graph = GetGraphLevel() > 0;
928  if (m_FeatLimit == 0 && has_coverage_graph) {
929  // use coverage graph instead to inprove performance
931  if (state != eCompleted)
932  return state;
933  } else {
934  CFeat_CI feature_iter(m_Handle.GetScope(), *loc, m_Sel);
935  int size = (int)feature_iter.GetSize();
937  if (feature_iter) {
938  // Get a more meaningful name
939  result->m_Desc = CSeqUtils::GetAnnotName(feature_iter->GetAnnot());
940  }
941 
942  // use the real feature limit
943  if (m_FeatLimit > 0) {
944  // we may want to adjust feature limit based on the
945  // actual screen size (in pixels) for this case
946  int new_limit = (int)(m_FeatLimit * m_Range.GetLength() / (1024 * m_Window));
947  //ERR_POST(Error << "FL adjusted from " << m_FeatLimit << " to " << new_limit << ",w:" << m_Window << ",r:" << m_Range.GetLength());
948  m_FeatLimit = max(m_FeatLimit, new_limit);
949  } else if (m_FeatLimit == -1) {
950  // unlimited, but still set a upper limit to guard against problem.
952  }
953 
954  // based on different limit settings to create different glyphs
955  if (m_FeatLimit == -2) {
956  // pack features into one line
957  SetTaskName("Packing features...");
958  EJobState state = x_CreateFeatSmear(feature_iter, result, result->m_Desc);
959  if (state != eCompleted)
960  return state;
961  } else if (m_FeatLimit >= 0) {
963  // in adaptive mode (m_FeatLimit != 0) and if number of feature is relatively small
964  // return both hstogram and feat glyphs and let feature track decide what to show
965  // based on the height of resulting track
967  if (m_FeatLimit != 0) {
968  if (size < m_FeatLimit || !m_Filter.empty()) {
969  x_GetLinkedFeatures(feature_iter, features);
970  size = static_cast<int>(features.size());
971  }
972  if (size < m_FeatLimit) { //m_FeatLimit == 0 is packed mode
973  CSeqGlyph::TObjects objs;
974  auto state = x_LinkFeatures(features, objs);
975  if (state != eCompleted)
976  return state;
977  result->m_ObjectList.swap(objs);
978  }
979  }
980  if (size > 0) {
981  // pack features into a histogram
982  if (has_coverage_graph) {
984  } else {
985  if (feature_iter)
986  state = x_CreateFeatHist(feature_iter, result, result->m_Desc);
987  else
988  state = x_CreateFeatHist(features, result, result->m_Desc);
989  }
990  } else {
991  state = eCompleted;
992  }
993  if (state != eCompleted)
994  return state;
995 
996  } else {
997  CSeqGlyph::TObjects objs;
998  auto state = x_LinkFeatures(feature_iter, objs);
999  if (state != eCompleted)
1000  return state;
1001  result->m_ObjectList.swap(objs);
1002  }
1004  }
1005  }
1006  } catch (CException& ex) {
1007  m_Error.Reset(new CAppJobError(ex.GetMsg()));
1008  return eFailed;
1009  } catch (std::exception& ex) {
1010  m_Error.Reset(new CAppJobError(ex.what()));
1011  return eFailed;
1012  }
1013 
1014  result->m_Token = m_Token;
1015  return eCompleted;
1016 }
1017 
1018 
1020  CLinkedFeature::TLinkedFeats& features,
1021  CFeatureFilter& filter)
1022 {
1023  bool passed = false;
1024  CLinkedFeature::TLinkedFeats::iterator p_iter = features.begin();
1025  while (p_iter != features.end()) {
1026  if (IsCanceled()) {
1027  return passed;
1028  }
1029 
1030  bool is_leaf = (*p_iter)->GetChildren().empty();
1031 
1032  // For features with child(ren), it will be treated as
1033  // passed if any of its children is passed.
1034  if ( (!is_leaf && x_FilterFeature_recursive((*p_iter)->GetChildren(), filter)) ||
1035  filter.Pass(&(*p_iter)->GetMappedFeature())) {
1036  ++p_iter;
1037  passed = true;
1038  } else {
1039  p_iter = features.erase(p_iter);
1040  }
1041  }
1042 
1043  return passed;
1044 }
1045 
1046 
1049  TFeatGroups& feat_groups)
1050 {
1051  feat_groups.clear();
1052  if (!m_Sorter) {
1053  feat_groups.emplace_back(kUnsortedGroupName, feats);
1054  return;
1055  }
1056 
1057  TFeatGroupMap group_map;
1058  x_SortFeature_recursive(feats, group_map);
1059  NON_CONST_ITERATE (TFeatGroupMap, grp_iter, group_map) {
1060  feat_groups.emplace_back(m_Sorter->GroupIdxToName(grp_iter->first), grp_iter->second);
1061  }
1062 }
1063 
1064 
1067  TFeatGroupMap& group_map)
1068 {
1069  CLinkedFeature::TLinkedFeats::iterator p_iter = feats.begin();
1070  while (p_iter != feats.end()) {
1071  if (IsCanceled()) {
1072  break;
1073  }
1074 
1075  bool is_leaf = (*p_iter)->GetChildren().empty();
1076  int idx = m_Sorter->GetGroupIdx((*p_iter)->GetMappedFeature());
1077 
1078  TFeatGroupMap child_group_map;
1079  if ( !is_leaf && m_Sorter->ChildFeatureFirst() ) {
1080  // sort the child features first
1081  x_SortFeature_recursive((*p_iter)->GetChildren(), child_group_map);
1082  }
1083 
1084  size_t grp_num = child_group_map.size();
1085  if (grp_num > 1) {
1086  // Child features fall in different groups, we need to clone
1087  // the parent feature to go with each group of chilren
1088  NON_CONST_ITERATE (TFeatGroupMap, grp_iter, child_group_map) {
1089  CRef<CLinkedFeature> p_feat(new CLinkedFeature((*p_iter)->GetMappedFeature()));
1090  p_feat->GetChildren() = grp_iter->second;
1091  group_map[grp_iter->first].push_back(p_feat);
1092  }
1093  ++p_iter;
1094  } else if (idx > -1 || grp_num == 1) {
1095  if (grp_num == 1) {
1096  // only one group of children, using child's group idx
1097  idx = child_group_map.begin()->first;
1098  }
1099  // else {
1100  // there is no child or no child falls in any target group,
1101  // and the parent feature (this feature) is good.
1102  // }
1103  group_map[idx].push_back(*p_iter);
1104  ++p_iter;
1105  } else {
1106  // unwanted feature, remove it
1107  p_iter = feats.erase(p_iter);
1108  }
1109  }
1110 }
1111 
1112 
1115  CLayoutGroup* group,
1116  int Level)
1117 {
1118  group->SetLevel(Level);
1119 
1120  bool need_group = features.size() > 1;
1122  if (IsCanceled()) return eCanceled;
1123 
1124  CRef<CSeqGlyph> glyph = x_CreateFeature1((*iter)->GetMappedFeature());
1125  glyph->SetLevel(Level);
1126  if ( !glyph ) continue;
1127 
1128  size_t num_children = (*iter)->GetChildren().size();
1130 
1131  // cut-off more than kMaxChildNum children, modifying the last glyph to show that cut-off
1132  if(num_children >= kMaxChildNum) {
1133  (*iter)->GetChildren().resize(kMaxChildNum);
1134  glyph->SetTearlineText(" (" + NStr::NumericToString(num_children - kMaxChildNum) + " features not shown)");
1135  }
1136  if (num_children == 0 ) {
1137  group->PushBack(glyph);
1138  if(Level == 0) {
1139  group->SetAsMaster(glyph);
1140  }
1141  } else if (num_children == 1 && m_LinkedFeat == ELinkedFeatDisplay::eLFD_ParentHidden) {
1142  // skip the parent feature (the created glyph)
1143  state = x_CreateFeature_Recursive((*iter)->GetChildren(), group, Level + 1);
1144  } else {
1145  CLayoutGroup* p_group = group;
1146  if (need_group) {
1147  CLayoutGroup* c_group = new CLayoutGroup(m_LinkedFeat);
1148  p_group->PushBack(c_group);
1149  p_group = c_group;
1150  }
1152  p_group->PushBack(glyph);
1153  if(Level == 0) {
1154  p_group->SetAsMaster(glyph);
1155  }
1156  }
1157 
1158  if (num_children > 1 && m_LinkedFeat != ELinkedFeatDisplay::eLFD_Expandable) {
1159  CLayoutGroup* cc_group = new CLayoutGroup(m_LinkedFeat);
1160  p_group->PushBack(cc_group);
1161  p_group = cc_group;
1162  }
1163 
1164  state = x_CreateFeature_Recursive((*iter)->GetChildren(), p_group, Level + 1);
1165  }
1166  if (state != eCompleted) {
1167  return state;
1168  }
1169 
1170  AddTaskCompleted(1);
1171  }
1172  return eCompleted;
1173 }
1174 
1175 
1177  CSeqGlyph::TObjects& objs)
1178 {
1179  SetTaskName("Creating feature glyphs...");
1180  SetTaskTotal((int)feature_iter.GetSize());
1181  SetTaskCompleted(0);
1182  for (; feature_iter ; ++feature_iter) {
1183  if (IsCanceled()) {
1184  return eCanceled;
1185  }
1186  if (CSeqUtils::IsCrossOrigin(feature_iter->GetLocation())) {
1187  vector<CRef<CSeqGlyph>> glyphs = x_CreateCrossOriginGlyphs(*feature_iter);
1188  for (const auto& it : glyphs) {
1189  if (!it) {
1190  objs.push_back(it);
1191  }
1192  }
1193  }
1194  else {
1195  CRef<CSeqGlyph> glyph = x_CreateFeature1(*feature_iter);
1196  if (glyph) {
1197  objs.push_back(glyph);
1198  }
1199  }
1200  AddTaskCompleted(1);
1201  }
1202  return eCompleted;
1203 }
1204 
1205 
1207  CSeqGlyph* parent_glyph /*=NULL*/,
1208  const char* label_prefix /*=NULL*/)
1209 {
1210  CConstRef<CSeq_loc> loc;
1211  if (m_Mapper) {
1212  try {
1213  loc = m_Mapper->Map(feat.GetLocation());
1214  } catch (std::exception&) {
1215  // ignore loc mapping exception.
1216  }
1217  } else {
1218  const CSeq_loc& loc_obj = feat.GetLocation();
1219  if (loc_obj.GetId()) {
1220  loc.Reset(&loc_obj);
1221  } else {
1222  // Very likely, we get a seq-loc with multiple seq-ids.
1223  // Extract the parts that matches with the viewed sequence
1224  loc = CSeqUtils::MixLocToLoc(loc_obj, m_Handle);
1225  }
1226  }
1227 
1228  auto GetCDSFrame = [&]() {
1229  if (feat.GetData().Which() != CSeqFeatData::e_Cdregion)
1230  return 0;
1231  if (feat.GetData().GetCdregion().IsSetFrame() && feat.GetData().GetCdregion().GetFrame() > 1)
1232  {
1233  int offset = feat.GetData().GetCdregion().GetFrame() - 1;
1234  const CSeq_loc& orig_loc = feat.GetLocation();
1235  ENa_strand q_strand = sequence::GetStrand(orig_loc, &m_Handle.GetScope());
1236  return (q_strand == eNa_strand_minus) ? -offset : offset;
1237  }
1238  return 0;
1239  };
1240  CRef<CSeqGlyph> glyph;
1241  if (loc) {
1242  if (loc->Which() != CSeq_loc::e_Null &&
1243  loc->Which() != CSeq_loc::e_Empty) {
1244  glyph = x_CreateFeature2(feat, *loc, label_prefix);
1245 
1246  // Try to find out if there is more accurate mapping
1247  // information available than the feature location itself.
1248  // For some features, such as RNA and CDS features, the
1249  // feature location might not be able to give the accureate mapping
1250  // between the RNA/CDS product sequence and the viewed sequence.
1251  // The inaccuracy prevent us from accurately showing the ruler
1252  // for the product sequence on the feature and mapping the
1253  // protein sequence or translated sequence to the feature intervals.
1254  // For performance consideration, we only do this when:
1255  // - the zoom level is at the sequence level,
1256  // - the feature has product sequence set,
1257  // - the feature is not projected from other sequences, and
1258  // - the feature is RNA or CDS feature.
1259  if (glyph && m_Window < kMinScaleForMapping && !m_Mapper && CSeqUtils::IsSameStrands(*loc)) {
1260 
1263  CSeqFeatData::ESubtype subtype = feat.GetData().GetSubtype();
1264 
1265  if (feat.IsSetProduct()) {
1266  const CSeq_loc& product = feat.GetProduct();
1267  const CSeq_id& product_id = *product.GetId();
1268 
1269  if (feat.GetData().IsRna()) {
1271  } else if (type == CSeqFeatData::e_Cdregion) {
1272  auto offset = GetCDSFrame();
1273  if (nullptr != parent_glyph) {
1274  // For CDS feature, we do this only when:
1275  // - the parent feature is a RNA feature, and
1276  // - the parent has mapping info set
1277  CFeatGlyph* parent_feat = dynamic_cast<CFeatGlyph*>(parent_glyph);
1278  if (parent_feat && !parent_feat->GetMappingInfo().empty() &&
1279  parent_feat->GetFeature().GetData().IsRna() && parent_feat->GetFeature().IsSetProduct()) {
1280 
1282  parent_feat->GetMappedFeature().GetMappedFeature(),
1283  feat, *loc, m_Handle.GetScope(), offset);
1284  }
1285  else {
1286  info = CSeqUtils::GetMappingInfoFromLocation(*loc, product_id, offset);
1287  }
1288  }
1289  else {
1290  info = CSeqUtils::GetMappingInfoFromLocation(*loc, product_id, offset);
1291  }
1292  }
1293  } else {
1294  // no product
1295  if ((type == CSeqFeatData::e_Cdregion) || (subtype == CSeqFeatData::eSubtype_V_segment) || feat.GetData().IsRna()) {
1296  static unsigned id_num{ 0 };
1297  CRef<CSeq_id> prod_id(new CSeq_id("lcl|pseudo" + NStr::IntToString(++id_num)));
1298  auto offset = GetCDSFrame();
1300  }
1301  }
1302 
1303  if ( !info.empty() ) {
1304  CFeatGlyph* feat_glyph = dynamic_cast<CFeatGlyph*>(glyph.GetPointer());
1305  if (feat_glyph) {
1306  feat_glyph->SetMappingInfo(info);
1307  }
1308  }
1309  }
1310  }
1311  } else {
1312  LOG_POST(Error << "CSGFeatureJob::x_CreateFeature1()"
1313  << "Failed to get seq-loc with unique seq-id!");
1314  }
1315 
1316  return glyph;
1317 }
1318 
1319 vector<CRef<CSeqGlyph>> CSGFeatureJob::x_CreateCrossOriginGlyphs(const CMappedFeat& feat, CSeqGlyph* parent_glyph, const char* label_prefix)
1320 {
1321  CConstRef<CSeq_loc> loc;
1322  if (m_Mapper) {
1323  try {
1324  loc = m_Mapper->Map(feat.GetLocation());
1325  }
1326  catch (std::exception&) {
1327  // ignore loc mapping exception.
1328  }
1329  }
1330  else {
1331  const CSeq_loc& loc_obj = feat.GetLocation();
1332  if (loc_obj.GetId()) {
1333  loc.Reset(&loc_obj);
1334  }
1335  else {
1336  // Very likely, we get a seq-loc with multiple seq-ids.
1337  // Extract the parts that matches with the viewed sequence
1338  loc = CSeqUtils::MixLocToLoc(loc_obj, m_Handle);
1339  }
1340  }
1341 
1342  auto GetCDSFrame = [&]() {
1343  if (feat.GetData().Which() != CSeqFeatData::e_Cdregion)
1344  return 0;
1345  if (feat.GetData().GetCdregion().IsSetFrame() && feat.GetData().GetCdregion().GetFrame() > 1)
1346  {
1347  int offset = feat.GetData().GetCdregion().GetFrame() - 1;
1348  const CSeq_loc& orig_loc = feat.GetLocation();
1349  ENa_strand q_strand = sequence::GetStrand(orig_loc, &m_Handle.GetScope());
1350  return (q_strand == eNa_strand_minus) ? -offset : offset;
1351  }
1352  return 0;
1353  };
1354 
1355  vector<CRef<CSeqGlyph>> glyphs;
1356  if (loc) {
1357  if (loc->Which() != CSeq_loc::e_Null &&
1358  loc->Which() != CSeq_loc::e_Empty) {
1359 
1360  CRef<CSeq_loc> range_loc(m_Handle.GetRangeSeq_loc(m_Range.GetFrom(), m_Range.GetTo()));
1361 
1362  for (CSeq_loc_CI loc_it(*loc); loc_it; ++loc_it) {
1363  CConstRef<CSeq_loc> gen_range_loc = loc_it.GetRangeAsSeq_loc();
1365  continue;
1366  }
1367 
1368  CRef<CSeq_loc> copy_loc(new CSeq_loc);
1369  copy_loc->Assign(*loc);
1370 
1371  CSeq_loc_I loc_i(*copy_loc);
1372  while (loc_i) {
1373  CSeq_loc_CI::TRange feat_range = loc_i.GetRange();
1374  CSeq_loc_CI::TRange gen_range = loc_it.GetRange();
1375  if (feat_range != gen_range) {
1376  loc_i.Delete();
1377  continue;
1378  }
1379  ++loc_i;
1380  }
1381  CRef<CSeq_loc> new_loc = loc_i.MakeSeq_loc();
1382  //LOG_POST(Info << "New location:\n" << MSerial_AsnText << new_loc.GetObject());
1383 
1384  CRef<CSeqGlyph> glyph = x_CreateFeature2(feat, *new_loc, label_prefix);
1385  if (glyph) {
1386  glyphs.push_back(glyph);
1387  }
1388 
1389  if (glyph && m_Window < kMinScaleForMapping && !m_Mapper && CSeqUtils::IsSameStrands(*new_loc)) {
1390 
1393  CSeqFeatData::ESubtype subtype = feat.GetData().GetSubtype();
1394 
1395  if (feat.IsSetProduct()) {
1396  const CSeq_loc& product = feat.GetProduct();
1397  const CSeq_id& product_id = *product.GetId();
1398 
1399  if (feat.GetData().IsRna()) {
1401  }
1402  else if (type == CSeqFeatData::e_Cdregion) {
1403  auto offset = GetCDSFrame();
1404  if (nullptr != parent_glyph) {
1405  // For CDS feature, we do this only when:
1406  // - the parent feature is a RNA feature, and
1407  // - the parent has mapping info set
1408  CFeatGlyph* parent_feat = dynamic_cast<CFeatGlyph*>(parent_glyph);
1409  if (parent_feat && !parent_feat->GetMappingInfo().empty() &&
1410  parent_feat->GetFeature().GetData().IsRna() && parent_feat->GetFeature().IsSetProduct()) {
1411 
1413  parent_feat->GetMappedFeature().GetMappedFeature(),
1414  feat, *new_loc, m_Handle.GetScope(), offset);
1415  }
1416  else {
1417  info = CSeqUtils::GetMappingInfoFromLocation(*new_loc, product_id, offset);
1418  }
1419  }
1420  else {
1421  info = CSeqUtils::GetMappingInfoFromLocation(*new_loc, product_id, offset);
1422  }
1423  }
1424  }
1425  else { // no product
1426  if ((type == CSeqFeatData::e_Cdregion) || (subtype == CSeqFeatData::eSubtype_V_segment) || feat.GetData().IsRna()) {
1427  static unsigned id_num{ 0 };
1428  CRef<CSeq_id> prod_id(new CSeq_id("lcl|pseudo" + NStr::IntToString(++id_num)));
1429  auto offset = GetCDSFrame();
1430  info = CSeqUtils::GetMappingInfoFromLocation(*new_loc, *prod_id, offset);
1431  }
1432  }
1433 
1434  if (!info.empty()) {
1435  CFeatGlyph* feat_glyph = dynamic_cast<CFeatGlyph*>(glyph.GetPointer());
1436  if (feat_glyph) {
1437  feat_glyph->SetMappingInfo(info);
1438  }
1439  }
1440  }
1441  }
1442  }
1443  } else {
1444  LOG_POST(Error << "CSGFeatureJob::x_CreateCrossOriginGlyphs()"
1445  << "Failed to get seq-loc with unique seq-id!");
1446  }
1447  return glyphs;
1448 }
1449 
1450 // This function should only be called for features crossing the origin of a circular sequence
1451 vector<CRef<CSeqGlyph>> CSGFeatureJob::x_CreateAndFilterCrossOriginGlyphs(const CMappedFeat& feat, const TSeqRange& range, CSeqGlyph* parent_glyph, const char* label_prefix)
1452 {
1454 
1455  vector<CRef<CSeqGlyph>> glyphs = x_CreateCrossOriginGlyphs(feat, parent_glyph, label_prefix);
1456  if (!glyphs.empty()) {
1457  vector<CRef<CSeqGlyph>>::iterator g_it = glyphs.begin();
1458  while (g_it != glyphs.end()) {
1459  if ((*g_it)->GetRange() != range) {
1460  g_it = glyphs.erase(g_it);
1461  }
1462  else {
1463  ++g_it;
1464  }
1465  }
1466  //LOG_POST(Info << "Nr of glyphs" << glyphs.size());
1467  //for (const auto& ii : glyphs) {
1468  // LOG_POST(Info << ii->GetRange().GetFrom() << ", " << ii->GetRange().GetTo());
1469  //}
1470  }
1471  return glyphs;
1472 
1473 }
1474 
1475 
1478  const CSeq_loc& loc,
1479  const char* label_prefix /*=NULL*/)
1480 {
1481  const CSeqFeatData& data = feat.GetData();
1482  if (data.GetSubtype() == CSeqFeatData::eSubtype_user) {
1483  const string& object_type = data.GetUser().GetType().GetStr();
1484  if (object_type == "clone placement") {
1485  return x_CreateCloneFeature(feat, loc);
1486  }
1487  }
1488 
1489  if (data.GetSubtype() == CSeqFeatData::eSubtype_clone) {
1490  return x_CreateCloneFeature(feat, loc);
1491  }
1492 
1493  CRef<CSeqGlyph> glyph;
1494  unique_ptr<CFeatGlyph> feat_glyph;
1495  if (data.GetSubtype() == CSeqFeatData::eSubtype_intron) {
1496  feat_glyph.reset(new CIntronGlyph(feat, loc, m_LinkedFeat));
1497  } else {
1498  feat_glyph.reset(new CFeatGlyph(feat, loc, m_LinkedFeat));
1499  }
1500  // cerr << "CFeatGlyph created: " << (void *) feat_glyph << endl;
1501  feat_glyph->SetFilter(m_Filter);
1502  if (label_prefix) {
1503  feat_glyph->SetTopLabelPrefix(label_prefix);
1504  }
1505  x_CalcIntervals(*feat_glyph);
1506  glyph.Reset(feat_glyph.release());
1507  return glyph;
1508 }
1509 
1510 
1513  const CSeq_loc& loc)
1514 {
1515  CRef<CSeqGlyph> glyph;
1516  CClonePlacementGlyph* cp = new CClonePlacementGlyph(feat, loc);
1517  glyph.Reset(cp);
1519  if (feat.GetLocation().IsMix()) {
1520  const CSeq_loc_mix::Tdata& seq_locs = feat.GetLocation().GetMix().Get();
1521  ITERATE (CSeq_loc_mix::Tdata, iter, seq_locs) {
1522  intervals.push_back((*iter)->GetTotalRange());
1523  }
1524  } else {
1525  intervals.push_back(feat.GetLocation().GetTotalRange());
1526  }
1527  return glyph;
1528 }
1529 
1530 
1531 
1534  const string& title)
1535 {
1536  if (features.empty()) return eCompleted;
1537 
1538  SetTaskName("Packing features...");
1540  for (const auto& f : features) {
1541  if (IsCanceled()) return eCanceled;
1542  try {
1543  the_map.AddRange(f->GetMappedFeature().GetLocation().GetTotalRange(), 1, false);
1544  } catch (CException&) {
1545  /// skip the feature with mix location and multiple seq-ids.
1546  }
1547  AddTaskCompleted(1);
1548  }
1549  CSeqFeatData::ESubtype subtype = features.front()->GetFeature().GetData().GetSubtype();
1550  result->m_ExtraObj.Reset(new CHistogramGlyph(the_map, subtype, title));
1551  return eCompleted;
1552 }
1553 
1554 
1556 {
1557  if (!feat_iter) return eCompleted;
1558  SetTaskName("Packing features...");
1559  CSeqFeatData::ESubtype subtype = feat_iter->GetOriginalFeature().GetData().GetSubtype();
1561  CFeatureFilter filter;
1562  filter.Init(m_Filter);
1563  for (; feat_iter; ++feat_iter) {
1564  if (IsCanceled()) {
1565  return eCanceled;
1566  }
1567  if (!filter.NeedFiltering() || filter.Pass(&(*feat_iter))) {
1568  try {
1569  the_map.AddRange(feat_iter->GetLocation().GetTotalRange(), 1, false);
1570  }
1571  catch (CException&) {
1572  /// skip the feature with mix location and multiple seq-ids.
1573  }
1574  }
1575  AddTaskCompleted(1);
1576  }
1577  result->m_ExtraObj.Reset(new CHistogramGlyph(the_map, subtype, title));
1578  return eCompleted;
1579 }
1580 
1583  int level,
1584  const string& title)
1585 {
1586  CSeqGlyph::TObjects glyphs;
1587  TAxisLimits tal;
1588  tal.min = 0.0;
1589  tal.max = 0.0;
1590  EJobState state = x_LoadCoverageGraph(glyphs, level, m_Window, title, false, tal);
1591  if (state == eCompleted && !glyphs.empty()) {
1592  _ASSERT(glyphs.size() == 1);
1593  result->m_ExtraObj = glyphs.front();
1594  }
1595  return state;
1596 }
1597 
1598 
1601  const string& title)
1602 {
1603  if ( !feat_iter ) return eCompleted;
1604 
1605  CHistogramGlyph::TMaps the_maps;
1606  for (; feat_iter ; ++feat_iter) {
1607  if (IsCanceled()) {
1608  return eCanceled;
1609  }
1610 
1611  size_t idx =
1613  string idx_str = NStr::IntToString((int)idx);
1614  CHistogramGlyph::TMaps::iterator iter = the_maps.find(idx_str);
1615  if (iter == the_maps.end()) {
1616  iter = the_maps.insert(
1618  idx_str,
1620  m_Range.GetFrom(),
1621  m_Range.GetTo(),
1622  (float)m_Window))).first;
1623  }
1624 
1625  try {
1626  iter->second.AddRange(
1627  feat_iter->GetLocation().GetTotalRange(), 1, false);
1628  } catch (CException&) {
1629  /// skip the feature with mix location and multiple seq-ids.
1630  }
1631  AddTaskCompleted(1);
1632  }
1633 
1634  if ( !the_maps.empty() ) {
1635  CRef<CHistogramGlyph> histogram(new CHistogramGlyph(the_maps, title));
1636  result->m_ExtraObj.Reset(histogram.GetPointer());
1637  }
1638 
1639  return eCompleted;
1640 }
1641 
1642 
1644 {
1645  CFeatGlyph::TIntervals& intervals = feat.SetIntervals();
1646  const CSeq_loc& loc = feat.GetLocation();
1647  intervals.clear();
1648  bool multi_ids = loc.IsMix() && loc.GetId() == NULL;
1649  CSeq_loc_CI iter(loc);
1650  if (multi_ids) {
1651  if (m_Handle) {
1652  for ( ; iter; ++iter) {
1653  if (m_Handle.IsSynonym(iter.GetSeq_id())) {
1654  intervals.push_back(iter.GetRange());
1655  }
1656  }
1657  }
1658  } else {
1659  bool rsite = false;
1660  if (feat.GetFeature().CanGetData())
1661  rsite = CSeqFeatData::eSubtype_rsite == feat.GetFeature().GetData().GetSubtype();
1662  TSeqRange rsiteRange;
1663  bool rsiteRangeFromSet = false;
1664  for ( ; iter; ++iter) {
1665  if (rsite) { // Assemble one range from the two points of the restriction site
1666  CConstRef<CSeq_loc> curr_loc = iter.GetRangeAsSeq_loc();
1667 
1668  if (curr_loc->IsPnt() && curr_loc->GetPnt().CanGetFuzz()) {
1669  const CSeq_point_Base::TFuzz &fuzz = curr_loc->GetPnt().GetFuzz();
1670  if (fuzz.IsLim() && (CInt_fuzz_Base::eLim_tl == fuzz.GetLim())) {
1671  if (!rsiteRangeFromSet) {
1672  rsiteRange.SetFrom(curr_loc->GetPnt().GetPoint());
1673  rsiteRangeFromSet = true;
1674  }
1675  else {
1676  rsiteRange.SetToOpen(curr_loc->GetPnt().GetPoint());
1677  intervals.push_back(rsiteRange);
1678  rsiteRangeFromSet = false;
1679  }
1680  }
1681  continue;
1682  }
1683  }
1684  intervals.push_back(iter.GetRange());
1685  }
1686  }
1687 }
1688 
1689 
1690 ///////////////////////////////////////////////////////////////////////////////
1691 /// CGeneModelFeatJob
1692 ///////////////////////////////////////////////////////////////////////////////
1693 
1694 
1696 CGeneModelFeatJob(const string& desc, CBioseq_Handle handle,
1697  const SAnnotSelector& lm_feat_sel,
1698  const SAnnotSelector& m_feat_sel,
1699  TJobToken lm_token, TJobToken main_token,
1700  bool landmark_feat, const TSeqRange& range, TModelUnit window,
1701  const CGeneModelConfig& conf, ICoordMapper* mapper)
1702  : CSGFeatureJob(desc, handle, lm_feat_sel, range, window, conf.m_LandmarkFeatLimit, ELinkedFeatDisplay::eLFD_Default, lm_token, mapper)
1703  , m_MainFeatSel(m_feat_sel)
1704  , m_MainFeatToken(main_token)
1705  , m_LandmarkFeats(landmark_feat)
1706  , m_Config(conf)
1707 {}
1708 
1709 
1711 {
1712  SetTaskName("Loading features...");
1713  CSGJobResult* result = new CSGJobResult();
1715 
1716  try {
1717  CConstRef<CSeq_loc> loc(m_Handle.GetRangeSeq_loc(m_Range.GetFrom(), m_Range.GetTo()) );
1718  // cerr << "Features for " << loc->GetId()->GetSeqIdString(true) << endl;
1719  // cerr << "using loc " << endl << MSerial_AsnText << *loc << endl;
1720 
1722  SAnnotSelector sel;
1723  if (m_LandmarkFeats) {
1724  sel = m_Sel;
1725  result->m_Token = m_Token;
1726  } else {
1727  sel = m_MainFeatSel;
1728  result->m_Token = m_MainFeatToken;
1729  }
1730 
1731  CFeat_CI feature_iter(m_Handle.GetScope(), *loc, sel);
1732 
1733  // if the visible genes are less than a certain number, we change the mode
1734  // to show all main features.
1735  if (m_LandmarkFeats &&
1736  feature_iter.GetSize() < (size_t)m_Config.m_OverviewFeatCutoff) {
1737  feature_iter = CFeat_CI(m_Handle.GetScope(), *loc, m_MainFeatSel);
1738  result->m_Token = m_MainFeatToken;
1739  m_LandmarkFeats = false;
1740  }
1741 
1742  // linking the features if not only landmark features are shown
1743  if (m_LandmarkFeats) {
1745  switch (f_type) {
1746  case eFilter_CCDS:
1749  feature_iter = CFeat_CI(m_Handle.GetScope(), *loc, sel);
1750  break;
1751  case eFilter_ncRNAs:
1752  case eFilter_dbref:
1756  feature_iter = CFeat_CI(m_Handle.GetScope(), *loc, sel);
1757  break;
1758  case eFilter_npcGenes:
1761  feature_iter = CFeat_CI(m_Handle.GetScope(), *loc, sel);
1762  break;
1763  default:
1764  break;
1765  }
1766 
1767  EJobState state;
1768  if (f_type != eFilter_invalid) {
1769  state = x_CreateFeaturesWithFilter(feature_iter, tmp, f_type);
1770  } else {
1771  state = x_CreateFeatures(feature_iter, tmp);
1772  }
1773  if (state != eCompleted) {
1774  return state;
1775  }
1776 
1777  // if feature number is more than the limit, we need to create a gene
1778  // distribution histogram and pick the most significant ones.
1779  if(m_FeatLimit > -1) {
1780  state = x_ProcessLandMarkFeatures(tmp, result->m_ExtraObj, result->m_CommentObjs);
1781  if (state != eCompleted) {
1782  return state;
1783  }
1784  }
1785  } else {
1786 
1788  // cerr << "got features: " << feature_iter.GetSize() << endl;
1789  for ( ; feature_iter; ++feature_iter) {
1790  const CMappedFeat& feat = *feature_iter;
1791  // cerr << "Got feature" << endl <<
1792  // MSerial_AsnText << feat.GetOriginalFeature() << endl;
1793  features.emplace_back(new CLinkedFeature(feat));
1794  }
1795 
1796  if ( !CSeqUtils::LinkFeatures(features, feature::CFeatTree::eFeatId_by_type, this) )
1797  return eCanceled;
1798 
1799  bool transcripts_filtered = false;
1800  EJobState state = x_CreateGeneModels(features, tmp, transcripts_filtered);
1801  if (state != eCompleted) {
1802  return state;
1803  }
1804  if (transcripts_filtered) {
1805  result->m_FilterDescr = "Some track data has been hidden";
1806  }
1807  }
1808  result->m_ObjectList.swap(tmp);
1809  } catch (CException& ex) {
1810  m_Error.Reset(new CAppJobError(ex.GetMsg()));
1811  return eFailed;
1812  } catch (std::exception& ex) {
1813  m_Error.Reset(new CAppJobError(ex.what()));
1814  return eFailed;
1815  }
1816 
1817  return eCompleted;
1818 }
1819 
1820 
1821 
1823  const CMappedFeat& feat, const CSeq_loc& loc, const char* label_prefix /*= NULL*/)
1824 {
1825  CFeatGlyph* feat_glyph;
1826  if (feat.GetData().IsCdregion()) {
1827  feat_glyph = new CCdsGlyph(feat, loc);
1828  } else {
1829  feat_glyph = new CFeatGlyph(feat, loc, m_LinkedFeat);
1830  }
1831  if (label_prefix) {
1832  feat_glyph->SetTopLabelPrefix(label_prefix);
1833  }
1834  CRef<CSeqGlyph> glyph(feat_glyph);
1835  x_CalcIntervals(*feat_glyph);
1836  return glyph;
1837 }
1838 
1839 static
1841 {
1842  ITERATE(CSeq_feat::TXref, xit, feat.GetXref()) {
1843  if ((*xit)->IsSetData() && (*xit)->GetData().Which() == choice) {
1844  return true;
1845  }
1846  }
1847  return false;
1848 }
1849 
1850 static
1851 bool s_HasCDS(const CLinkedFeature& linked_feat)
1852 {
1853  for (const auto& it : linked_feat.GetChildren()) {
1854  if (it->GetFeature().GetData().IsCdregion())
1855  return true;
1856  }
1857  return false;
1858 }
1859 
1860 static
1861 bool s_IsGnomonModel(const CSeq_feat& feat)
1862 {
1863 /* Alternative method (needs scope)
1864  if (feat.IsSetProduct()) {
1865  const CSeq_id* product_id = feat.GetProduct().GetId();
1866  if (product_id) {
1867  string acc = sequence::GetAccessionForId(*product_id, m_Handle.GetScope());
1868  auto acc_info = CSeq_id::IdentifyAccession(acc);
1869  if (acc_info == CSeq_id::eAcc_refseq_mrna_predicted || CSeq_id::eAcc_refseq_ncrna_predicted)
1870  break;
1871  }
1872  }
1873 */
1874  if (!feat.IsSetExt()) {
1875  return false;
1876  }
1877  const CUser_object & ext = feat.GetExt();
1878  if (!ext.IsSetType() || !ext.IsSetData()) {
1879  return false;
1880  }
1881  const CUser_object_Base::TType & ext_type = ext.GetType();
1882  if (!ext_type.IsStr() || ext_type.GetStr() != "CombinedFeatureUserObjects") {
1883  return false;
1884  }
1885  const CUser_object::TData & ext_data = ext.GetData();
1886  ITERATE(CUser_object::TData, field_iter, ext_data) {
1887  const CUser_field & field = **field_iter;
1888  if (!field.IsSetLabel() || !field.IsSetData())
1889  continue;
1890  const CUser_field::TLabel & field_label = field.GetLabel();
1891  const CUser_field::TData & field_data = field.GetData();
1892  if (!field_label.IsStr() || !field_data.IsObject() || field_label.GetStr() != "ModelEvidence")
1893  continue;
1894  const CUser_object & evidence_object = field_data.GetObject();
1895  if (!evidence_object.IsSetData() ||
1896  !evidence_object.IsSetType() ||
1897  !evidence_object.GetType().IsStr() ||
1898  evidence_object.GetType().GetStr() != "ModelEvidence")
1899  continue;
1900  const CUser_object::TData & evidence_data = evidence_object.GetData();
1901  ITERATE(CUser_object::TData, evidence_iter, evidence_data) {
1902  const CUser_field & evidence_field = **evidence_iter;
1903  if (!evidence_field.IsSetLabel() || !evidence_field.GetLabel().IsStr()
1904  || evidence_field.GetLabel().GetStr() != "Method" ||
1905  !evidence_field.IsSetData() ||
1906  !evidence_field.GetData().IsStr())
1907  continue;
1908  return NStr::FindNoCase(evidence_field.GetData().GetStr(), "Gnomon") != NPOS;
1909  }
1910  }
1911  return false;
1912 }
1913 
1914 static
1915 bool s_HasTag(const CSeq_feat& feat, const set<string>& tags)
1916 {
1917  if (tags.empty() || !feat.IsSetQual())
1918  return false;
1919  for (const auto& iter : feat.GetQual()) {
1920  if (iter->GetQual() == "tag" && iter->IsSetVal()) {
1921  const string& val = iter->GetVal();
1922  if (tags.count(val) > 0)
1923  return true;
1924  }
1925  }
1926  return false;
1927 }
1928 
1929 static
1930 bool s_IsSelect(const CLinkedFeature& feat)
1931 {
1932  return s_HasTag(feat.GetFeature(), {"MANE Select", "RefSeq Select"});
1933 }
1934 
1935 static bool s_IsCCDS(const CLinkedFeature& linked_feat) {
1936  const CSeq_feat& feat = linked_feat.GetFeature();
1937  if (feat.GetData().IsCdregion())
1938  return feat.GetNamedDbxref("CCDS") || s_HasTag(feat, {"CCDS"});
1939  ITERATE(CLinkedFeature::TLinkedFeats, iter, linked_feat.GetChildren()) {
1940  if (s_IsCCDS(**iter))
1941  return true;
1942  }
1943  return false;
1944 }
1945 
1947 {
1948  if (!feat.GetFeature().GetData().IsRna())
1949  return true;
1950 
1951  if (m_Config.m_HideNonCoding && s_HasCDS(feat) == false)
1952  return false;
1953 
1955  return false;
1956 
1957  if (m_Config.m_CCDSOnly && !s_IsCCDS(feat))
1958  return false;
1959 
1960  if (m_Config.m_SelectOnly && !s_IsSelect(feat))
1961  return false;
1962 
1963  return true;
1964 }
1965 
1968 {
1969  SetTaskName("Creating feature glyphs and gene models...");
1970  SetTaskTotal((int)feats.size());
1971  SetTaskCompleted(0);
1972  transcripts_filtered = false;
1974 
1975  // Create glyph for each feature, and put the linked features
1976  // into right group according to the feature merging style
1978  AddTaskCompleted(1);
1979  if (IsCanceled()) return eCanceled;
1980 
1981  bool skip = false;
1982  switch (f_type) {
1983  case eFilter_dbref:
1984  if (!x_IsDbref(m_Filter, **iter)) {
1985  skip = true;
1986  }
1987  break;
1988  case eFilter_CCDS:
1989  if (!x_IsCCDS(**iter)) {
1990  skip = true;
1991  }
1992  break;
1993  case eFilter_pseudo_genes:
1994  if (!x_IsPseudoGene((*iter)->GetFeature())) {
1995  skip = true;
1996  }
1997  break;
1998  case eFilter_ncRNAs:
1999  if (!x_IsncRNA(**iter)) {
2000  skip = true;
2001  }
2002  break;
2003  case eFilter_npcGenes:
2004  if (!x_IsnpcGene(**iter)) {
2005  skip = true;
2006  }
2007  break;
2008  default:
2009  break;
2010  }
2011 
2012  if (skip) continue;
2013 
2014  vector<CRef<CSeqGlyph>> glyphs;
2015  if (CSeqUtils::IsCrossOrigin((*iter)->GetMappedFeature().GetLocation())) {
2016  glyphs = x_CreateCrossOriginGlyphs((*iter)->GetMappedFeature());
2017  if (glyphs.empty()) {
2018  continue;
2019  }
2020  }
2021  else {
2022  CRef<CSeqGlyph> glyph = x_CreateFeature1((*iter)->GetMappedFeature());
2023  if (!glyph) continue;
2024  glyphs.push_back(glyph);
2025  }
2026 
2027  CSeqFeatData::ESubtype subtype = (*iter)->GetFeature().GetData().GetSubtype();
2028 
2029  if ((*iter)->GetChildren().empty()) {
2030  if (m_Config.m_ShowGenes == false && subtype == CSeqFeatData::eSubtype_gene && x_IsPseudoGene((*iter)->GetFeature())) {
2031  bool is_filtered = (m_Config.m_HideNonCoding || m_Config.m_CCDSOnly || m_Config.m_SelectOnly);
2032  if (is_filtered) {
2033  transcripts_filtered = true;
2034  continue;
2035  }
2036  }
2037  if (m_Config.m_HideNonCoding) {
2038  switch (subtype) {
2041  continue;
2042  default:
2043  break;
2044  }
2045  }
2046  for (const auto& it : glyphs) {
2047  objs.push_back(it);
2048  }
2049  continue;
2050  }
2051 
2052  if (subtype == CSeqFeatData::eSubtype_gene) {
2053  if (m_Config.m_ShowGenes == false && x_IsPseudoGene((*iter)->GetFeature())) {
2054  bool is_filtered = (m_Config.m_HideNonCoding || m_Config.m_CCDSOnly || m_Config.m_SelectOnly);
2055  if (is_filtered) {
2056  transcripts_filtered = true;
2057  continue;
2058  }
2059  }
2060  }
2061 
2062  for (const auto& glyph_it : glyphs) {
2063  // for each sub-glyph of a cross-origin glyph
2064  // most of the time the vector will have a single element
2065 
2066  CRef<CSeqGlyph> glyph = glyph_it;
2067  auto current_range = glyph->GetRange();
2068 
2069  if (subtype == CSeqFeatData::eSubtype_gene) {
2070 
2071  CRef<CLayoutGroup> misc_group(new CLayoutGroup);
2072  CRef<CLinkedFeatsGroup> rnacds_group(new CLinkedFeatsGroup);
2073  CRef<CLayoutGroup> exon_group;
2074  string label_prefix;
2075  feature::GetLabel((*iter)->GetFeature(), &label_prefix, feature::fFGL_Content);
2076 
2077  size_t num_filtered = 0;
2078  NON_CONST_ITERATE(CLinkedFeature::TLinkedFeats, g_iter, (*iter)->GetChildren()) {
2079  vector<CRef<CSeqGlyph>> g_glyphs;
2080  if (CSeqUtils::IsCrossOrigin((*g_iter)->GetMappedFeature().GetLocation())) {
2081  g_glyphs = x_CreateAndFilterCrossOriginGlyphs((*g_iter)->GetMappedFeature(), current_range, 0, label_prefix.c_str());
2082  if (g_glyphs.empty())
2083  continue;
2084  }
2085  else {
2086  CRef<CSeqGlyph> g_glyph = x_CreateFeature1((*g_iter)->GetMappedFeature(), 0, label_prefix.c_str());
2087  if (!g_glyph) continue;
2088  g_glyphs.push_back(g_glyph);
2089  }
2090 
2091  _ASSERT(g_glyphs.size() == 1);
2092 
2093  CSeqFeatData::E_Choice s_type = (*g_iter)->GetFeature().GetData().Which();
2094  CSeqFeatData::ESubtype s_subtype = (*g_iter)->GetFeature().GetData().GetSubtype();
2095  if (s_subtype == CSeqFeatData::eSubtype_exon) {
2096  if (!exon_group)
2097  exon_group.Reset(new CLayoutGroup);
2098  exon_group->PushBack(g_glyphs[0]);
2099 
2100  }
2101  else if (s_subtype == CSeqFeatData::eSubtype_cdregion) {
2102  rnacds_group->PushBack(g_glyphs[0]);
2103  }
2104  else if ((s_type != CSeqFeatData::e_Rna && s_subtype != CSeqFeatData::eSubtype_misc_RNA)
2105  && (s_subtype != CSeqFeatData::eSubtype_V_segment) && (s_subtype != CSeqFeatData::eSubtype_D_segment)
2106  && (s_subtype != CSeqFeatData::eSubtype_J_segment) && (s_subtype != CSeqFeatData::eSubtype_C_region)) {
2107  misc_group->PushBack(g_glyphs[0]);
2108  }
2109  else { /// must be RNA
2110  if (x_IsTranscriptAcceptable(**g_iter)) {
2111  bool has_children = !(*g_iter)->GetChildren().empty() || s_HasFeatXref((*g_iter)->GetFeature(), CSeqFeatData::e_Cdregion);
2112  if (m_Config.m_MergeStyle == CGeneModelConfig::eMerge_Pairs && has_children) {
2113  CLinkedFeatsGroup* rna_group = new CLinkedFeatsGroup();
2114  rnacds_group->PushBack(rna_group);
2115  rna_group->PushBack(g_glyphs[0]);
2116 
2117  NON_CONST_ITERATE(CLinkedFeature::TLinkedFeats, r_iter, (*g_iter)->GetChildren()) {
2118  if (CSeqUtils::IsCrossOrigin((*r_iter)->GetMappedFeature().GetLocation())) {
2119  vector<CRef<CSeqGlyph>> r_glyphs = x_CreateAndFilterCrossOriginGlyphs((*r_iter)->GetMappedFeature(), current_range, g_glyphs[0].GetPointer(), label_prefix.c_str());
2120  for (const auto& g_it : r_glyphs) {
2121  rna_group->PushBack(g_it.GetNCPointerOrNull());
2122  }
2123  }
2124  else {
2125  CRef<CSeqGlyph> r_glyph = x_CreateFeature1((*r_iter)->GetMappedFeature(), g_glyphs[0].GetPointer(), label_prefix.c_str());
2126  if (r_glyph) {
2127  rna_group->PushBack(r_glyph);
2128  }
2129  }
2130  }
2131  }
2132  else { // eMerge_All, eMerge_No, eMerge_OneLine, and eMerge_Pairs when no CDSs present
2133  rnacds_group->PushBack(g_glyphs[0]);
2134  NON_CONST_ITERATE(CLinkedFeature::TLinkedFeats, r_iter, (*g_iter)->GetChildren()) {
2135  if (CSeqUtils::IsCrossOrigin((*r_iter)->GetMappedFeature().GetLocation())) {
2136  vector<CRef<CSeqGlyph>> r_glyphs = x_CreateAndFilterCrossOriginGlyphs((*r_iter)->GetMappedFeature(), current_range, g_glyphs[0].GetPointer(), label_prefix.c_str());
2137  for (const auto& g_it : r_glyphs) {
2138  rnacds_group->PushBack(g_it.GetNCPointerOrNull());
2139  }
2140  }
2141  else {
2142  CRef<CSeqGlyph> r_glyph = x_CreateFeature1((*r_iter)->GetMappedFeature(), g_glyphs[0].GetPointer(), label_prefix.c_str());
2143  if (r_glyph) {
2144  rnacds_group->PushBack(r_glyph);
2145  }
2146  }
2147  }
2148  }
2149  }
2150  else {
2151  num_filtered += 1;
2152  transcripts_filtered = true;
2153  }
2154  }
2155  }
2156 
2157  bool is_filtered = (num_filtered > 0 && num_filtered == (*iter)->GetChildren().size());
2158  // no gene bar if all children were filtered out and rendering options indicate sno gene bar
2159  if (m_Config.m_ShowGenes || is_filtered == false) {
2160 
2161  CGeneGroup* group = new CGeneGroup();
2162  objs.emplace_back(group);
2163  group->PushBack(glyph.GetNCPointerOrNull());
2164 
2165  if (!misc_group->GetChildren().empty() && m_Config.m_MergeStyle != CGeneModelConfig::eMerge_OneLine) {
2166  if (misc_group->GetChildren().size() > 1) {
2167  group->PushBack(misc_group);
2168  }
2169  else {
2170  group->Append(misc_group->SetChildren());
2171  }
2172  }
2173  if (!rnacds_group->GetChildren().empty()) {
2174  if (rnacds_group->GetChildren().size() == 1 ||
2177  {
2178  // Merge group children, dissolve the group
2179  group->Append(rnacds_group->SetChildren());
2180  }
2181  else {
2182  // Add as a group
2183  group->PushBack(rnacds_group);
2184  }
2185  }
2186  if (exon_group &&
2187  (m_Config.m_MergeStyle != CGeneModelConfig::eMerge_OneLine || rnacds_group->GetChildren().empty())) {
2188  if (exon_group->GetChildren().size() > 1) {
2189  group->PushBack(exon_group);
2190  }
2191  else {
2192  group->Append(exon_group->SetChildren());
2193  }
2194  }
2195 
2196  }
2197 
2198  }
2199  else { // must be RNA or other misc features: VDJ segments, C regions, and enhancers
2200  if ((*iter)->GetChildren().empty()) {
2201  // no need to put it into a group
2202  objs.push_back(glyph);
2203  }
2204  else {
2205  CLayoutGroup* group = NULL;
2207  group = new CLayoutGroup();
2208  objs.push_back(CRef<CSeqGlyph>(group));
2209  }
2210  else {
2211  CLinkedFeatsGroup* rc_group = new CLinkedFeatsGroup();
2212  objs.push_back(CRef<CSeqGlyph>(rc_group));
2213  group = &rc_group->SetGroup();
2214  }
2215  group->PushBack(glyph.GetNCPointerOrNull());
2216  NON_CONST_ITERATE(CLinkedFeature::TLinkedFeats, r_iter, (*iter)->GetChildren()) {
2217  vector<CRef<CSeqGlyph>> r_glyphs;
2218  if (CSeqUtils::IsCrossOrigin((*r_iter)->GetMappedFeature().GetLocation())) {
2219  vector<CRef<CSeqGlyph>> r_glyphs = x_CreateAndFilterCrossOriginGlyphs((*r_iter)->GetMappedFeature(), current_range, glyph.GetNCPointer());
2220  for (const auto& g_it : r_glyphs) {
2221  group->PushBack(g_it.GetNCPointerOrNull());
2222  }
2223 
2224  }
2225  else {
2226  CRef<CSeqGlyph> r_glyph = x_CreateFeature1((*r_iter)->GetMappedFeature(), glyph.GetNCPointer());
2227  if (r_glyph) {
2228  group->PushBack(r_glyph);
2229  }
2230  }
2231  }
2232  }
2233  }
2234  }
2235  }
2236 
2237  return eCompleted;
2238 }
2239 
2240 
2243  CSeqGlyph::TObjects& objs,
2244  TFilterType filter)
2245 {
2246  if (filter == eFilter_pseudo_genes) {
2247  SetTaskName("Creating feature glyphs...");
2248  SetTaskTotal((int)feature_iter.GetSize());
2249  SetTaskCompleted(0);
2250  for (; feature_iter ; ++feature_iter) {
2251  if (IsCanceled()) {
2252  return eCanceled;
2253  }
2254 
2255  AddTaskCompleted(1);
2256  if ( !x_IsPseudoGene(feature_iter->GetOriginalFeature()) ) {
2257  continue;
2258  }
2259 
2260  CRef<CSeqGlyph> glyph = x_CreateFeature1(*feature_iter);
2261  if (glyph) {
2262  objs.push_back(glyph);
2263  }
2264  }
2265  } else {
2267  for ( ; feature_iter; ++feature_iter) {
2268  const CMappedFeat& feat = *feature_iter;
2269  CRef<CLinkedFeature> fref( new CLinkedFeature(feat) );
2270  features.push_back(fref);
2271  }
2272  if ( !CSeqUtils::LinkFeatures(features,
2273  feature::CFeatTree::eFeatId_by_type, this) ) {
2274  return eCanceled;
2275  }
2276 
2277  SetTaskName("Creating feature glyphs...");
2278  SetTaskTotal((int)features.size());
2279  SetTaskCompleted(0);
2281  AddTaskCompleted(1);
2282 
2283  if ( !(*iter)->GetFeature().GetData().IsGene() ) continue;
2284 
2285  if (IsCanceled()) return eCanceled;
2286 
2287  bool skip = false;
2288  switch (filter) {
2289  case eFilter_dbref:
2290  if ( !x_IsDbref(m_Filter, **iter) ) {
2291  skip = true;
2292  }
2293  break;
2294  case eFilter_CCDS:
2295  if ( !x_IsCCDS(**iter) ) {
2296  skip = true;
2297  }
2298  break;
2299  case eFilter_ncRNAs:
2300  if ( !x_IsncRNA(**iter) ) {
2301  skip = true;
2302  }
2303  break;
2304  case eFilter_npcGenes:
2305  if ( !x_IsnpcGene(**iter) ) {
2306  skip = true;
2307  }
2308  break;
2309  default:
2310  break;
2311  }
2312 
2313  if (skip) continue;
2314 
2315  CRef<CSeqGlyph> glyph = x_CreateFeature1((*iter)->GetMappedFeature());
2316  if (glyph) {
2317  objs.push_back(glyph);
2318  }
2319  }
2320  }
2321  return eCompleted;
2322 }
2323 
2324 
2325 //float s_GetGeneDocsumWeight(const CEntrez2_docsum& ds)
2326 //{
2327 // float score = 0;
2328 // try {
2329 // string val = ds.GetValue("GeneWeight");
2330 // score = (float)NStr::StringToDouble(val);
2331 // }
2332 // catch (CException&) {
2333 // }
2334 // return score;
2335 //}
2336 
2337 
2339 
2340 static const char* kGeneByLocUrl =
2341 "http://www.ncbi.nlm.nih.gov/gutils/fgenes_by_loc.fcgi?sort=weight&retmode=asnb";
2342 
2344  TGi gi, const TSeqRange& r, size_t retmax)
2345 {
2346  STimeout timeout;
2347  timeout.sec = 4;
2348  timeout.usec = 0;
2349 
2350  string url = kGeneByLocUrl;
2351  url += "&gi=" + NStr::NumericToString(gi);
2352  url += "&retmax=" + NStr::NumericToString(retmax);
2353  url += "&start=" + NStr::NumericToString(r.GetFrom());
2354  url += "&stop=" + NStr::NumericToString(r.GetTo());
2355  CConn_HttpStream stream(url, fHTTP_AutoReconnect, &timeout);
2356 
2357  unique_ptr<CObjectIStream> obj_stream(CObjectIStream::Open(eSerial_AsnBinary, stream));
2358  try {
2359  CGBL_Reply gbl_reply;
2360  //NcbiStreamCopy(cout, stream);
2361  *obj_stream >> gbl_reply;
2362  if (gbl_reply.IsError()) {
2363  NCBI_THROW(CException, eUnknown, gbl_reply.GetError());
2364  }
2365  const CGBL_Data& data = gbl_reply.GetData();
2366  if (data.CanGetGenes()) {
2367  int weight = data.GetReturned();
2368  ITERATE (CGBL_Data::TGenes, iter, data.GetGenes()) {
2369  genes.insert(map<int, int>::value_type((*iter)->GetGeneid(), weight--));
2370  }
2371  }
2372  } catch (CException& e) {
2373  LOG_POST(Error << "Failed to retrieve genes by location for gi|"
2374  << gi << ", error: " << e.GetMsg());
2375  return false;
2376  }
2377 
2378  return true;
2379 }
2380 
2381 
2383  CSeqGlyph::TObjects& objs, CRef<CSeqGlyph>& hist_obj, CSeqGlyph::TObjects& comment_objs)
2384 {
2385  SetTaskName("Packing features...");
2386  SetTaskTotal((int)objs.size());
2387  SetTaskCompleted(0);
2388 
2389 
2390  vector<SLandmarkFeat> landmark_feats;
2391 
2392  ///
2393  /// determine scores for landmark features
2394  ///
2395 
2396 #if 0
2397  ///
2398  /// option 1: brain-dead calculation
2399  ///
2400  NON_CONST_ITERATE(CSeqGlyph::TObjects, iter, objs) {
2401  if (m_StopRequested) {
2402  return eCanceled;
2403  }
2404 
2405  CSeqGlyph* tmp = *iter;
2406  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(tmp);
2407 
2408  TSeqRange range = tmp->GetRange();
2409 
2410  float score = (float)range.GetLength();
2411  string s;//s.erase();
2413  score /= s.length();
2414 
2415  SLandmarkFeat f;
2416  f.score = score;
2417  f.obj = *iter;
2418 
2419  landmark_feats.push_back(f);
2420  }
2421 
2422  ///
2423  /// end option 1
2424  ///
2425 #endif
2426 
2427 #if 0
2428  /// option 2: use gene weights
2429  /// NB: this currently uses an ineffective method, in that it
2430  /// queries Entrez for the information on the fly
2431  vector<int> gene_uids;
2432  NON_CONST_ITERATE(CSeqGlyph::TObjects, iter, objs) {
2433  if (m_StopRequested) {
2434  return eCanceled;
2435  }
2436 
2437  CSeqGlyph* tmp = *iter;
2438  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(tmp);
2439  const CSeq_feat& seqfeat = feat->GetFeature();
2440  CConstRef<CDbtag> gene_tag = seqfeat.GetNamedDbxref("GeneID");
2441  if ( !gene_tag ) {
2442  gene_tag = seqfeat.GetNamedDbxref("LocusID");
2443  }
2444  if (gene_tag && gene_tag->GetTag().IsId()) {
2445  gene_uids.push_back(gene_tag->GetTag().GetId());
2446  }
2447  }
2448 
2449  typedef map<int, float> TScoreMap;
2450  TScoreMap gene_scores;
2451 
2452  /// screen for already retrieved gene IDs
2453  CEntrezCache& cache = CEntrezCache::GetInstance();
2454  {{
2455  vector<int>::iterator iter = gene_uids.begin();
2456  string db("gene");
2457  for ( ; iter != gene_uids.end(); ) {
2458  CConstRef<CEntrez2_docsum> ds = cache.Get(db, *iter);
2459  if (ds) {
2460  gene_scores[ds->GetUid()] =
2461  s_GetGeneDocsumWeight(*ds);
2462  iter = gene_uids.erase(iter);
2463  } else {
2464  ++iter;
2465  }
2466  }
2467  }}
2468 
2469  /// retrieve any new gene IDs
2470  if (gene_uids.size()) {
2471  CEntrez2Client cli;
2472  CRef<CEntrez2_docsum_list> ds = cli.GetDocsums(gene_uids, "gene");
2473  if (ds && ds->IsSetList()) {
2474  cache.Put("gene", *ds);
2475  ITERATE (CEntrez2_docsum_list::TList, iter, ds->GetList()) {
2476  gene_scores[(*iter)->GetUid()] =
2477  s_GetGeneDocsumWeight(**iter);
2478  }
2479  }
2480  }
2481 
2482  NON_CONST_ITERATE(CSeqGlyph::TObjects, iter, objs) {
2483  if (m_StopRequested) {
2484  return eCanceled;
2485  }
2486 
2487  CSeqGlyph* tmp = *iter;
2488  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(tmp);
2489  const CSeq_feat& seqfeat = feat->GetFeature();
2490  float score = 0;
2491 
2492  CConstRef<CDbtag> gene_tag = seqfeat.GetNamedDbxref("GeneID");
2493  if ( !gene_tag ) {
2494  gene_tag = seqfeat.GetNamedDbxref("LocusID");
2495  }
2496  if (gene_tag && gene_tag->GetTag().IsId()) {
2497  int uid = gene_tag->GetTag().GetId();
2498  TScoreMap::iterator it = gene_scores.find(uid);
2499  if (it != gene_scores.end()) {
2500  score = it->second;
2501  }
2502  }
2503 
2504  SLandmarkFeat f;
2505  f.score = score;
2506  f.obj = *iter;
2507 
2508  landmark_feats.push_back(f);
2509  }
2510 
2511  ///
2512  /// end option 2
2513  ///
2514 #endif
2515 
2516  TId2Wt gene_weights;
2517 #if 0
2518  // Gene weights are available for current live gis only
2519  if (m_Handle.GetState() == CBioseq_Handle::fState_none) {
2520  // try to get the sorted (by weight) gene list
2521  CSeq_id_Handle idh = m_Handle.GetSeq_id_Handle();
2522  idh = sequence::GetId(idh, m_Handle.GetScope(), sequence::eGetId_ForceGi);
2523  if (idh && idh.GetGi() > 0) {
2524  TGi gi = idh.GetGi();
2525  int number_genes = m_FeatLimit > 0 ? m_FeatLimit : (int)objs.size();
2526  typedef map<int, int> TId2Wt; // gene id to gene weight map
2527  if (number_genes > 0) {
2528  s_GetGeneWeight(gene_weights, gi, m_Range, number_genes);
2529  }
2530  }
2531  }
2532 #endif
2533 
2534 #if 1
2535  ///
2536  /// option 4: use gene weights from user objects
2537  ///
2538  NON_CONST_ITERATE(CSeqGlyph::TObjects, iter, objs) {
2539  if (IsCanceled()) {
2540  return eCanceled;
2541  }
2542 
2543  CSeqGlyph* tmp = *iter;
2544  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(tmp);
2545  const CSeq_feat& seqfeat = feat->GetFeature();
2546  float score = 0.0f;
2547 
2548  if (gene_weights.empty()) {
2549 // weight use removed per SV-4623
2550 /* if (seqfeat.IsSetExt()) {
2551  const CUser_object& obj = seqfeat.GetExt();
2552  CConstRef<CUser_field> field = obj.GetFieldRef("GeneWeight");
2553  if (field) {
2554  if (field->GetData().IsInt()) {
2555  score = (float)field->GetData().GetInt();
2556  } else if (field->GetData().IsReal()) {
2557  score = (float)field->GetData().GetReal();
2558  }
2559  }
2560  }
2561 */
2562  if ( !score ) {
2563  string s;
2565  TSeqRange range = tmp->GetRange();
2566 
2567  score = (float)range.GetLength();
2568  score /= s.length();
2569  score -= 1e6f;
2570  }
2571  } else if (CConstRef<CDbtag> tag = seqfeat.GetNamedDbxref("GeneID")) {
2572  if (tag->GetTag().IsId()) {
2573  TId2Wt::const_iterator g_iter = gene_weights.find(tag->GetTag().GetId());
2574  if (g_iter != gene_weights.end()) {
2575  score = (float)g_iter->second;
2576  }
2577  }
2578  }
2579 
2580  SLandmarkFeat f;
2581  f.score = score;
2582  f.obj = *iter;
2583 
2584  landmark_feats.push_back(f);
2585  }
2586 
2587  ///
2588  /// end option 3
2589  ///
2590 #endif
2591 
2592  if (landmark_feats.empty()) return eCompleted;
2593 
2594  ///
2595  ///
2596  ///
2597  /// sort and filter
2598  std::sort(landmark_feats.begin(), landmark_feats.end(),
2600 
2601  // Add Gene Histogram when there are genes that are not shown
2602  if ((int)landmark_feats.size() > m_FeatLimit && m_Config.m_ShowHistogram) {
2603  const CFeatGlyph* feat =
2604  dynamic_cast<const CFeatGlyph*>(landmark_feats.front().obj.GetPointer());
2605  string title = CSeqUtils::GetAnnotName(feat->GetMappedFeature().GetAnnot());
2606 
2607  CHistogramGlyph::TMap the_map(
2608  m_Range.GetFrom(), m_Range.GetTo(), (float)m_Window);
2609  ITERATE (vector<SLandmarkFeat>, iter, landmark_feats) {
2610  if (IsCanceled()) {
2611  return eCanceled;
2612  }
2613 
2614  TSeqRange range = iter->obj->GetRange();
2615  the_map.AddRange(range);
2616  AddTaskCompleted(1);
2617  }
2618 
2619  hist_obj.Reset(new CHistogramGlyph(the_map, CSeqFeatData::eSubtype_gene, title));
2620  }
2621 
2622  size_t len = landmark_feats.size() - 1;
2623  vector<SLandmarkFeat>::iterator prev =
2624  landmark_feats.begin() + ((int)len < m_FeatLimit ? len : m_FeatLimit);
2625  vector<SLandmarkFeat>::iterator s_iter = prev;
2626  vector<SLandmarkFeat>::iterator end = landmark_feats.end();
2627  //for (++iter; iter != end; ++iter) {
2628  // if (iter->score != prev->score) {
2629  // break;
2630  // }
2631  // prev = iter;
2632  //}
2633  if (IsCanceled()) {
2634  return eCanceled;
2635  }
2636 
2637  landmark_feats.erase(s_iter, end);
2638 
2639  int highlight_num = (int)(10 * m_Range.GetLength() / (1400 * m_Window));
2640  if (highlight_num > 40) {
2641  highlight_num = 40;
2642  } else if (highlight_num < 10) {
2643  highlight_num = 10;
2644  }
2645 
2646  if (m_Config.m_HighlightMode == 1) {
2647  // highlight the top most important genes
2648  s_iter = landmark_feats.begin();
2649  while (highlight_num > 0 && s_iter != landmark_feats.end()) {
2650  s_iter->obj->SetHighlighted(true);
2651  --highlight_num;
2652  ++s_iter;
2653  }
2654  } else if (m_Config.m_HighlightMode == 2) {
2655  // render label and feature independently
2656  s_iter = landmark_feats.begin();
2657  while (highlight_num > 0 && s_iter != landmark_feats.end()) {
2658  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(s_iter->obj.GetPointer());
2659  string label;
2661  CCommentGlyph* comment = new CCommentGlyph(label, s_iter->obj);
2662  CRef<CSeqGlyph> glyph(comment);
2663  TSeqRange range = feat->GetRange();
2664  comment->SetTargetPos(TModelPoint((range.GetFrom() + range.GetTo()) * 0.5, 0.0));
2665  comment_objs.push_back(glyph);
2666  --highlight_num;
2667  ++s_iter;
2668  }
2669  }
2670 
2671  std::sort(landmark_feats.begin(), landmark_feats.end(),
2673 
2674  if (IsCanceled()) {
2675  return eCanceled;
2676  }
2677 
2678  objs.clear();
2679  ITERATE (vector<SLandmarkFeat>, l_iter, landmark_feats) {
2680  objs.push_back(l_iter->obj);
2681  }
2682 
2683  return eCompleted;
2684 }
2685 
2686 
2687 vector<string> CGeneModelFeatJob::GetFilters(const CBioseq_Handle& handle,
2688  const TSeqRange& range,
2689  SAnnotSelector& sel,
2690  const string& filter)
2691 {
2692  vector<string> filters;
2693  TFilterType f_type = x_FilterStrToValue(filter);
2694  switch (f_type) {
2695  case eFilter_dbref_all:
2697  break;
2698  case eFilter_dbref:
2699  {{
2703  CFeat_CI feat_iter(handle, range, sel);
2704  while (feat_iter) {
2705  if (x_IsDbref(filter, feat_iter->GetOriginalFeature())) {
2706  filters.push_back(filter);
2707  break;
2708  }
2709  ++feat_iter;
2710  }
2711  break;
2712  }}
2713  case eFilter_CCDS:
2714  {{
2716  CFeat_CI feat_iter(handle, range, sel);
2717  while (feat_iter) {
2718  if (x_IsDbref(filter, feat_iter->GetOriginalFeature())) {
2719  filters.push_back(filter);
2720  break;
2721  }
2722  ++feat_iter;
2723  }
2724  break;
2725  }}
2726  case eFilter_pseudo_genes:
2727  {{
2729  CFeat_CI feat_iter(handle, range, sel);
2730  while (feat_iter) {
2731  if (x_IsPseudoGene(feat_iter->GetOriginalFeature())) {
2732  filters.push_back(filter);
2733  break;
2734  }
2735  ++feat_iter;
2736  }
2737  break;
2738  }}
2739  case eFilter_ncRNAs:
2740  {{
2744  CFeat_CI feat_iter(handle, range, sel);
2746  for (; feat_iter; ++feat_iter) {
2747  const CMappedFeat& feat = *feat_iter;
2748  CRef<CLinkedFeature> fref( new CLinkedFeature(feat) );
2749  features.push_back(fref);
2750  }
2751  CSeqUtils::LinkFeatures(features,
2752  feature::CFeatTree::eFeatId_by_type, NULL);
2753  ITERATE (CLinkedFeature::TLinkedFeats, iter, features) {
2754  if (x_IsncRNA(**iter)) {
2755  filters.push_back(filter);
2756  break;
2757  }
2758  }
2759  break;
2760  }}
2761  case eFilter_npcGenes:
2762  {{
2765  CFeat_CI feat_iter(handle, range, sel);
2767  for (; feat_iter; ++feat_iter) {
2768  const CMappedFeat& feat = *feat_iter;
2769  CRef<CLinkedFeature> fref( new CLinkedFeature(feat) );
2770  features.push_back(fref);
2771  }
2772  CSeqUtils::LinkFeatures(features,
2773  feature::CFeatTree::eFeatId_by_type, NULL);
2774  ITERATE (CLinkedFeature::TLinkedFeats, iter, features) {
2775  if (x_IsnpcGene(**iter)) {
2776  filters.push_back(filter);
2777  break;
2778  }
2779  }
2780  break;
2781  }}
2782  default:
2783  break;
2784  }
2785  return filters;
2786 }
2787 
2788 
2791 {
2792  /// anything unrecognizable will be treated as dbref
2794  if (NStr::EqualNocase(filter, "dbref")) {
2796  } else if (NStr::EqualNocase(filter, "CCDS")) {
2797  type = eFilter_CCDS;
2798  } else if (NStr::EqualNocase(filter, "PseudoGenes")) {
2800  } else if (NStr::EqualNocase(filter, "ncRNAs")) {
2801  type = eFilter_ncRNAs;
2802  } else if (NStr::EqualNocase(filter, "npcGenes")) {
2804  } else if ( !filter.empty() ) {
2805  type = eFilter_dbref;
2806  }
2807 
2808  return type;
2809 }
2810 
2811 
2812 ///////////////////////////////////////////////////////////////////////////////
2813 /// CBatchFeatJob
2814 ///////////////////////////////////////////////////////////////////////////////
2815 CBatchFeatJob::CBatchFeatJob(const string& desc,
2816  CBioseq_Handle handle,
2817  const TSeqRange& range, TModelUnit window,
2818  TJobToken token, const TFeatBatchJobRequests& requests)
2819  : CSGFeatureJob(desc, handle, SAnnotSelector(), range, window, token)
2820  , m_Requests(requests)
2821 {
2822 }
2823 
2824 
2826 {
2827  try {
2830  result->m_Token = m_Token;
2831 
2833  if (IsCanceled()) {
2834  return eCanceled;
2835  }
2836  CRef<CSGJobResult> single_res =
2837  x_LoadFeatProducts(iter->m_Feat, iter->m_Sel);
2838  if (single_res) {
2839  result->m_Results.push_back(single_res);
2840  }
2841  }
2842  } catch (CException& ex) {
2843  m_Error.Reset(new CAppJobError(ex.GetMsg()));
2844  return eFailed;
2845  } catch (std::exception& ex) {
2846  m_Error.Reset(new CAppJobError(ex.what()));
2847  return eFailed;
2848  }
2849 
2850  return eCompleted;
2851 }
2852 
2853 
2856  const SAnnotSelector& sel)
2857 {
2860  CRef<CSeqGlyph> dmap;
2861 
2862  const CSeq_loc& loc = feat->GetLocation();
2863  const CSeq_loc& product = feat->GetFeature().GetProduct();
2864  try {
2865  // map visible range to product feature
2866  CSeq_loc_Mapper prot_range_mapper(loc, product, &GetScope());
2867 
2869  range.IntersectWith(loc.GetTotalRange());
2870  CRef<CSeq_loc> tmp_loc(new CSeq_loc());
2871  tmp_loc->SetInt().SetFrom(range.GetFrom());
2872  tmp_loc->SetInt().SetTo (range.GetTo());
2873  tmp_loc->SetId(*loc.GetId());
2874 
2875  // our new location for feature iterator
2876  CRef<CSeq_loc> prot_loc = prot_range_mapper.Map(tmp_loc.GetObject());
2877  prot_loc->SetId(*product.GetId());
2878 
2879 
2880  // might be slow if number of visible features in the frame are more than a 100
2881  // if slow, try not to recreate seq_mapper for each feature
2882  CRef<CSeq_loc_Mapper> mapper;
2883  CAlign_CI align_iter(GetScope(), loc, sel);
2884 
2885  while (align_iter && !mapper) {
2886  // find the first seq-align that matches the current feature product sequence
2887  const CSeq_align& align = *align_iter;
2888  CSeq_align::TDim num_row = align.CheckNumRows();
2889  for (CSeq_align::TDim row = 0; row < num_row; ++row) {
2890  if (product.GetId()->Match(align.GetSeq_id(row))) {
2891  mapper.Reset(
2892  new CSeq_loc_Mapper(align, *loc.GetId(), &GetScope()));
2893  break;
2894  }
2895  }
2896  ++align_iter;
2897  }
2898 
2899  if ( !mapper ) {
2900  mapper.Reset( new CSeq_loc_Mapper(product, loc, &GetScope()) );
2901  }
2902 
2903  // use newly created location to get the features
2904  CFeat_CI feat_iter(GetScope(), prot_loc.GetObject(), sel);
2905  size_t size = feat_iter.GetSize();
2906 
2907  // Only show variation in packed form in non-sequence level
2908  bool packed = feat_iter &&
2910  m_Window > kSeqZoomLevel &&
2911  size * 1024 * m_Window / range.GetLength() > 50.0;
2912 
2913  if (packed) {
2914  CHistogramGlyph::TMap the_map(feat->GetRange().GetFrom(),
2915  feat->GetRange().GetTo(), (float)m_Window);
2916 
2917  for ( ; feat_iter; ++feat_iter) {
2918  CConstRef<CSeq_loc> mapped_loc =
2919  mapper->Map(feat_iter->GetLocation());
2920  the_map.AddRange( mapped_loc->GetTotalRange() );
2921  }
2922  dmap.Reset(new CHistogramGlyph(
2925 
2926  } else if (size > 0) {
2927  for ( ; feat_iter; ++feat_iter) {
2928  // see the comment about performance above
2929  CConstRef<CSeq_loc> mapped_loc = mapper->Map(feat_iter->GetLocation());
2930  if (mapped_loc->Which() != CSeq_loc::e_Null &&
2931  mapped_loc->Which() != CSeq_loc::e_Empty) {
2932  const CMappedFeat mapped_feat = *feat_iter;
2933  tmp.push_back(x_CreateFeature2(mapped_feat, *mapped_loc));
2934  }
2935  }
2936  }
2937  }
2938  catch (CAnnotMapperException&) {
2939  /// ignore errors from location mapping
2940  return result;
2941  }
2942 
2943  result.Reset(new CSGJobResult());
2944  if (dmap) result->m_ExtraObj.Reset(dmap);
2945  if ( !tmp.empty() ) result->m_ObjectList.swap(tmp);
2946  result->m_Token = m_Token;
2947  result->m_Owner = CRef<CSeqGlyph>(feat.GetPointer());
2948  return result;
2949 }
2950 
2951 
2952 
2953 ///////////////////////////////////////////////////////////////////////////////
2954 /// CSGCalcFeatHistJob
2955 ///////////////////////////////////////////////////////////////////////////////
2957 {
2958  try {
2959  CSGJobResult* result = new CSGJobResult();
2961 
2963  the_map(m_Range.GetFrom(), m_Range.GetTo(), (float)m_Window);
2965  if (IsCanceled()) {
2966  EJobState state = x_CalcFeatHistRecursive(*iter, the_map);
2967  if (state != eCompleted) {
2968  return state;
2969  }
2970  }
2971  }
2972 
2973  CRef<CSeqGlyph> dmap;
2975 
2976  result->m_ExtraObj.Reset(dmap);
2977  result->m_Token = m_Token;
2978  } catch (CException& ex) {
2979  m_Error.Reset(new CAppJobError(ex.GetMsg()));
2980  return eFailed;
2981  } catch (std::exception& ex) {
2982  m_Error.Reset(new CAppJobError(ex.what()));
2983  return eFailed;
2984  }
2985 
2986  return eCompleted;
2987 }
2988 
2989 
2992  CDensityMap<float>& the_map)
2993 {
2994  CLayoutGroup* group = dynamic_cast<CLayoutGroup*>(obj.GetPointer());
2995  if (group) {
2996  ITERATE (CLayoutGroup::TObjectList, iter, group->GetChildren()) {
2997  if (IsCanceled()) {
2998  EJobState state = x_CalcFeatHistRecursive(*iter, the_map);
2999  if (state != eCompleted) {
3000  return state;
3001  }
3002  }
3003  }
3004  return eCompleted;
3005  }
3006 
3007  CFeatGlyph* feat = dynamic_cast<CFeatGlyph*>(obj.GetPointer());
3008  if (feat) {
3009  const CSeqFeatData& data = feat->GetFeature().GetData();
3010  if ( data.GetSubtype() == CSeqFeatData::eSubtype_mRNA ||
3011  data.GetSubtype() == CSeqFeatData::eSubtype_cdregion) {
3012  // collect intervals
3013  ITERATE (CFeatGlyph::TIntervals, iter, feat->GetIntervals()) {
3014  TSeqRange range = *iter;
3015 
3016  if (IsCanceled()) {
3017  return eCanceled;
3018  }
3019 
3020  the_map.AddRange(range);
3021  }
3022  }
3023  }
3024 
3025  return eCompleted;
3026 }
3027 
3028 
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
CAlign_CI –.
Definition: align_ci.hpp:63
Seq-loc and seq-align mapper exceptions.
const TAnnotNames & GetAnnotNames(void) const
size_t GetSize(void) const
CAppJobError Default implementation for IAppJobError - encapsulates a text error message.
CBatchFeatJob: a job class for loading annotated features from a given a set of sequences within the ...
Definition: feature_ds.cpp:387
virtual CRef< CSGJobResult > x_LoadFeatProducts(CRef< CFeatGlyph > feat, const SAnnotSelector &sel)
virtual EJobState x_Execute()
method truly doing the job.
TFeatBatchJobRequests m_Requests
Definition: feature_ds.cpp:401
CBatchFeatJob(const string &desc, CBioseq_Handle handle, const TSeqRange &range, TModelUnit window, TJobToken token, const TFeatBatchJobRequests &requests)
CBatchFeatJob.
CBatchJobResult – the data structure holding the seqgraphic job results for a batch job processing.
CBioseq_Handle –.
CCloneConcordancySorter is a feature sorter used to sort clone features based on clone concordancy.
static const string & GetID()
CClonePlacementGlyph is similar to CFeatureGlyph, but with different rendering style and settings.
TIntervals & SetIntervals()
CClonePlacementGlyph inline implementations.
CCommentGlyph – utility class for having comments in graphical glyphs.
void SetTargetPos(const TModelPoint &pos)
This stream exchanges data with an HTTP server located at the URL: http[s]://host[:port]/path[?...
CDbvarClinicalAsstSorter is a feature sorter used to sort variant features based on variant quality.
static const string & GetID()
CDbvarPilotSorter is a feature sorter used to sort variant features based on variant pilot number.
static const string & GetID()
CDbvarQualitySorter is a feature sorter used to sort variant features based on variant quality.
static const string & GetID()
CDbvarSamplesetTypeSorter is a feature sorter used to sort variant features based on variant quality.
static const string & GetID()
CDbvarValidationSorter is a feature sorter used to sort variant features based on variant quality.
static const string & GetID()
CRef< CEntrez2_docsum_list > GetDocsums(const vector< TUid > &uids, const string &db)
Retrieve the docsums for a set of UIDs.
void SetMappingInfo(const TMappingInfo &info)
TIntervals & SetIntervals()
CFeatGlyph inline implementations.
const TMappingInfo & GetMappingInfo() const
virtual const objects::CSeq_loc & GetLocation(void) const
access the position of this object.
void SetTopLabelPrefix(const char *prefix)
Set prefix to prepend to labels on top.
const objects::CMappedFeat & GetMappedFeature(void) const
Access a new, fully remapped feature.
virtual TSeqRange GetRange(void) const
get the total range of this object.
virtual const TIntervals & GetIntervals(void) const
access sub-intervals (if any).
const objects::CSeq_feat & GetFeature(void) const
Access the original feature.
static size_t GetCustomColorIdx(const objects::CSeq_feat &feat)
Get the customized color idx for a given feature.
void GetLabel(string &label, CLabel::ELabelType type) const
retrieve feature label for a given type
static const string & GetID()
Definition: feature_ds.hpp:140
CFeat_CI –.
Definition: feat_ci.hpp:64
class CFeatureFilter
bool NeedFiltering() const
bool Pass(const objects::CMappedFeat *feat)
void Init(const string &filter)
CGBL_Data –.
Definition: GBL_Data.hpp:66
CGBL_Reply –.
Definition: GBL_Reply.hpp:66
CGRCStatusSorter is a feature sorter used to sort GRC issue features based on resolving status stored...
static const string & GetID()
CGeneGroup is a subclass of CLayoutGroup contains gene, RNA, cds, and Exon features.
bool m_CCDSOnly
Show only CCDS variants.
EMergeStyle m_MergeStyle
the way on how to merge CDSs and RNAs.
bool m_SelectOnly
Show only Select/MANE variants.
bool m_HideNonCoding
Hide transcripts without associated CDS.
bool m_ShowHistogram
show gene distribution histogram.
@ eMerge_OneLine
merge into one line
@ eMerge_Pairs
merge each transcript and CDS pair
@ eMerge_No
show all feature individually
bool m_HideModels
Hide Model RefSeqs.
CGeneModelFeatJob: a job class for loading annotated main features, including genes,...
Definition: feature_ds.cpp:232
static vector< string > GetFilters(const CBioseq_Handle &handle, const TSeqRange &range, SAnnotSelector &sel, const string &filter)
static bool x_IsncRNA(const CLinkedFeature &linked_feat)
Definition: feature_ds.cpp:337
static bool x_IsDbref(const string &db, const CSeq_feat &feat)
Definition: feature_ds.cpp:284
virtual CRef< CSeqGlyph > x_CreateFeature2(const CMappedFeat &feat, const CSeq_loc &loc, const char *label_prefix=NULL)
overridable creator.
IAppJob::EJobState x_CreateFeaturesWithFilter(CFeat_CI &feature_iter, CSeqGlyph::TObjects &objs, TFilterType filter)
create features when there is a filter set up.
static bool x_IsnpcGene(const CLinkedFeature &linked_feat)
Definition: feature_ds.cpp:360
static TFilterType x_FilterStrToValue(const string &filter)
static bool x_IsCCDS(const CLinkedFeature &linked_feat)
Definition: feature_ds.cpp:311
static bool x_IsDbref(const string &db, const CLinkedFeature &linked_feat)
Definition: feature_ds.cpp:296
bool x_IsTranscriptAcceptable(const CLinkedFeature &feat)
Check if transcript passes Config filters.
IAppJob::EJobState x_CreateGeneModels(CLinkedFeature::TLinkedFeats &feats, CSeqGlyph::TObjects &objs, bool &transcripts_filtered)
Link features into a hierarchical list.
SAnnotSelector m_MainFeatSel
annotation selector for all main features.
Definition: feature_ds.cpp:375
EJobState x_ProcessLandMarkFeatures(CSeqGlyph::TObjects &objs, CRef< CSeqGlyph > &hist_obj, CSeqGlyph::TObjects &comment_objs)
TJobToken m_MainFeatToken
Job token for loading main features.
Definition: feature_ds.cpp:376
CGeneModelConfig m_Config
Definition: feature_ds.cpp:378
CGeneModelFeatJob(const string &desc, CBioseq_Handle handle, const SAnnotSelector &lm_feat_sel, const SAnnotSelector &m_feat_sel, TJobToken lm_token, TJobToken main_token, bool landmark_feat, const TSeqRange &range, TModelUnit window, const CGeneModelConfig &conf, ICoordMapper *mapper)
CGeneModelFeatJob.
@ eFilter_dbref
one specific dbref
Definition: feature_ds.cpp:237
@ eFilter_dbref_all
any dbref
Definition: feature_ds.cpp:236
@ eFilter_CCDS
genes with Consensus CDS
Definition: feature_ds.cpp:238
bool m_LandmarkFeats
is overview mode?
Definition: feature_ds.cpp:377
static bool x_IsPseudoGene(const CSeq_feat &feat)
Definition: feature_ds.cpp:332
virtual EJobState x_Execute()
method truly doing the job.
CRef< TData > GetData(const string &data_key)
Retrieves TData from in-memory cache or if not found calls TData::Init to initialize new TData instan...
static CGraphCache & GetInstance()
Definition: graph_cache.hpp:97
CRef< TData > GetCachedData(const string &data_key)
Retrieves TData from in-memory cache.
static int GetNearestLevel(const set< int > &levels, double zoom)
Definition: graph_utils.cpp:47
CLayoutGroup is a container of CSeqGlyphs (layout objects).
void PushBack(CSeqGlyph *obj)
Append a layout object to the end.
TObjectList & SetChildren()
const TObjectList & GetChildren() const
CLayoutGroup inline methods.
void SetAsMaster(CRef< CSeqGlyph > master)
master glyph has some special meaning (e.g.
void Append(TObjectList &objs)
size_t GetChildrenNum() const
Get total number of children.
ILayoutPolicy::TObjectList TObjectList
CLinkedFeatsGroup is a container class contains related features.
CLayoutGroup & SetGroup()
void PushBack(CSeqGlyph *obj)
CMappedFeat –.
Definition: mapped_feat.hpp:59
CTitleGroup is a layout group with a title.
Definition: named_group.hpp:45
objects::SAnnotSelector m_Sel
our annotation selector
objects::CScope & GetScope(void) const
CSGAnnotJob inline methods.
int GetGraphLevel() const
TSeqRange m_Range
target range
objects::CBioseq_Handle m_Handle
target sequence
IAppJob::EJobState x_LoadCoverageGraph(CSeqGlyph::TObjects &glyphs, int level, TModelUnit window, const string &title, bool fixed_scale, const TAxisLimits &y_limits)
CSGCalcFeatHistJob.
Definition: feature_ds.cpp:409
TSeqRange m_Range
target range
Definition: feature_ds.cpp:430
TModelUnit m_Window
current window for smear bars
Definition: feature_ds.cpp:431
EJobState x_CalcFeatHistRecursive(CRef< CSeqGlyph > obj, CDensityMap< float > &the_map)
CSGCalcFeatHistJob(const string &desc, const CSeqGlyph::TObjects &objs, const TSeqRange &range, TModelUnit window, TJobToken token)
Definition: feature_ds.cpp:411
const CSeqGlyph::TObjects & m_Objects
Definition: feature_ds.cpp:429
virtual EJobState x_Execute()
CSGCalcFeatHistJob.
virtual ISGDataSource * CreateDS(SConstScopedObject &object) const
create an instance of the layout track type using default settings.
Definition: feature_ds.cpp:551
virtual string GetExtensionLabel() const
returns a displayable label for this extension ( please capitalize the key words - "My Extension" )
Definition: feature_ds.cpp:567
virtual bool IsSharable() const
check if the data source can be shared.
Definition: feature_ds.cpp:574
virtual string GetExtensionIdentifier() const
returns the unique human-readable identifier for the extension the id should use lowercase letters se...
Definition: feature_ds.cpp:560
CSGFeatureDS.
Definition: feature_ds.hpp:49
string m_Filter
Definition: feature_ds.hpp:110
CSGFeatureDS(objects::CScope &scope, const objects::CSeq_id &id)
CSGFeatureDS.
Definition: feature_ds.cpp:438
void LoadGeneModelFeatures(objects::SAnnotSelector &lm_feat_sel, objects::SAnnotSelector &m_feat_sel, TJobToken lm_token, TJobToken main_token, bool landmark_feat, const TSeqRange &range, TModelUnit window, const CRef< CGeneModelConfig > &conf)
load features for gene model.
Definition: feature_ds.cpp:488
void GetAnnotNames(objects::SAnnotSelector &sel, const TSeqRange &range, TAnnotNameTitleMap &names) const
Definition: feature_ds.cpp:519
string m_GraphCacheKey
Definition: feature_ds.hpp:112
void CalcFeatHistogram(const CSeqGlyph::TObjects &objs, const TSeqRange &range, TModelUnit window, TJobToken token=-1)
Definition: feature_ds.cpp:508
bool IsVcfTabix() const
Definition: feature_ds.hpp:210
string m_SortBy
Definition: feature_ds.hpp:111
bool IsBigBed() const
Definition: feature_ds.hpp:204
virtual void LoadFeatures(objects::SAnnotSelector &sel, const TSeqRange &range, TModelUnit window, TJobToken token=-1, int max_feat=-1, ELinkedFeatDisplay LinkedFeatDisplay=ELinkedFeatDisplay::eLFD_Default, const string &extra_filter="")
void GetAnnotNames_var(objects::SAnnotSelector &sel, const TSeqRange &range, TAnnotNameTitleMap &names) const
Definition: feature_ds.cpp:528
vector< string > GetFilters(const string &annot_name, const TSeqRange &range) const
Definition: feature_ds.cpp:537
CSGFeatureJob: a job class for loading annotated features from a given sequence and visible range.
Definition: feature_ds.cpp:93
CRef< CSeqGlyph > x_CreateCloneFeature(const CMappedFeat &feat, const CSeq_loc &loc)
bool x_FilterFeature_recursive(CLinkedFeature::TLinkedFeats &features, CFeatureFilter &filter)
void x_GetLinkedFeatures(CFeat_CI &feature_iter, CLinkedFeature::TLinkedFeats &features)
Definition: feature_ds.cpp:742
IAppJob::EJobState x_CreateFeatSmear(CFeat_CI &feat_iter, CSGJobResult *result, const string &title)
int m_FeatLimit
the maximum number of features allowed.
Definition: feature_ds.cpp:210
void SetVcfCacheKey(const string &cache_key)
Definition: feature_ds.cpp:124
void x_SortFeatures(CLinkedFeature::TLinkedFeats &feats, TFeatGroups &feat_groups)
bool x_ProcessCachedVcfTabix()
Definition: feature_ds.cpp:871
IAppJob::EJobState x_LinkFeatures(CLinkedFeature::TLinkedFeats &feats, CSeqGlyph::TObjects &objs)
Definition: feature_ds.cpp:771
bool x_ProcessCachedBigBed()
Definition: feature_ds.cpp:840
void x_CalcIntervals(CFeatGlyph &feat)
CSGFeatureJob(const string &desc, CBioseq_Handle handle, const SAnnotSelector &sel, const TSeqRange &range, TModelUnit window, TJobToken token)
Definition: feature_ds.cpp:642
vector< TSortedFeats > TFeatGroups
Definition: feature_ds.cpp:96
EJobState x_CreateFeatHist(CLinkedFeature::TLinkedFeats &features, CSGJobResult *result, const string &title)
CRef< CSeqGlyph > x_CreateFeature1(const CMappedFeat &feat, CSeqGlyph *parent_glyph=NULL, const char *label_prefix=NULL)
CIRef< ICoordMapper > m_Mapper
Definition: feature_ds.cpp:218
string m_VcfCacheKey
Definition: feature_ds.cpp:221
void x_SortFeature_recursive(CLinkedFeature::TLinkedFeats &feats, TFeatGroupMap &group_map)
ELinkedFeatDisplay m_LinkedFeat
controls creation of parent or child features
Definition: feature_ds.cpp:213
TModelUnit m_Window
current window for smear bars
Definition: feature_ds.cpp:204
vector< CRef< CSeqGlyph > > x_CreateCrossOriginGlyphs(const CMappedFeat &feat, CSeqGlyph *parent_glyph=nullptr, const char *label_prefix=nullptr)
static void GetAnnotNames_var(const CBioseq_Handle &handle, const TSeqRange &range, SAnnotSelector &sel, TAnnotNameTitleMap &names)
Definition: feature_ds.cpp:722
IAppJob::EJobState x_CreateFeature_Recursive(CLinkedFeature::TLinkedFeats &features, CLayoutGroup *group, int Level)
CIRef< IFeatSorter > m_Sorter
Definition: feature_ds.cpp:216
map< int, CLinkedFeature::TLinkedFeats > TFeatGroupMap
Definition: feature_ds.cpp:97
string m_BigBedCacheKey
Definition: feature_ds.cpp:220
void SetBigBedCacheKey(const string &cache_key)
Definition: feature_ds.cpp:119
vector< CRef< CSeqGlyph > > x_CreateAndFilterCrossOriginGlyphs(const CMappedFeat &feat, const TSeqRange &range, CSeqGlyph *parent_glyph=nullptr, const char *label_prefix=nullptr)
IAppJob::EJobState x_CreateFeatures(CFeat_CI &feature_iter, CSeqGlyph::TObjects &objs)
static void GetAnnotNames(const CBioseq_Handle &handle, const TSeqRange &range, SAnnotSelector &sel, TAnnotNameTitleMap &names)
Definition: feature_ds.cpp:703
EJobState x_CreateFeatHistFromGraph(CSGJobResult *result, int level, const string &title)
pair< string, CLinkedFeature::TLinkedFeats > TSortedFeats
Definition: feature_ds.cpp:95
void SetSortBy(const string &sortby)
Definition: feature_ds.cpp:670
virtual EJobState x_Execute()
method truly doing the job.
Definition: feature_ds.cpp:907
virtual CRef< CSeqGlyph > x_CreateFeature2(const CMappedFeat &feat, const CSeq_loc &loc, const char *label_prefix=NULL)
overridable creator.
void SetFilter(const string &filter)
Definition: feature_ds.cpp:114
CIRef< ICoordMapper > m_Mapper
coordinate mapper between mapped features coord. and sequence coord.
TJobID x_LaunchJob(IAppJob &job, int report_period=1, const string &pool="ObjManagerEngine")
Launch either a background or foreground job.
bool m_Adaptive
adaptive/exact annot selector
int m_Depth
annotation resolving depth
TGraphLevels m_GraphLevels
Existing coverage graph levels.
objects::CBioseq_Handle m_Handle
CSGJobResult – the data structure holding the seqgraphic job results.
CScope –.
Definition: scope.hpp:92
ESubtype GetSubtype(void) const
class CSeqGlyph defines an interface that wraps a rectilinear abstract object.
Definition: seq_glyph.hpp:82
virtual TSeqRange GetRange(void) const
get the total range of this object.
Definition: seq_glyph.hpp:513
virtual bool LessBySeqPos(const CSeqGlyph &obj) const
compare this object to another based on glyph sequence position.
Definition: seq_glyph.hpp:534
void SetLevel(int Level)
Definition: seq_glyph.hpp:287
void SetTearlineText(const string &sTearlineText)
tearline text – if set, is appended to the glyph name (does not naffect processing otherwise)
Definition: seq_glyph.hpp:277
list< CRef< CSeqGlyph > > TObjects
Definition: seq_glyph.hpp:85
CSeqGraphicJob – the base class of seqgraphic job for handling the job status such as reporting the p...
CRef< CObject > m_Result
virtual void SetTaskTotal(int total)
map< string, string > TAnnotNameTitleMap
List of annotations with the corresponding titles.
virtual void SetTaskName(const string &name)
virtual void SetTaskCompleted(int completed)
set total finished task number.
void SetToken(TJobToken token)
CSeqGraphicJob inline methods.
virtual void AddTaskCompleted(int delta)
set to add newly finished task number.
TJobToken m_Token
Job token recognizable by job listener.
CRef< CAppJobError > m_Error
TDim CheckNumRows(void) const
Validatiors.
Definition: Seq_align.cpp:73
const CSeq_id & GetSeq_id(TDim row) const
Get seq-id (the first one if segments have different ids).
Definition: Seq_align.cpp:317
namespace ncbi::objects::
Definition: Seq_feat.hpp:58
CConstRef< CDbtag > GetNamedDbxref(const CTempString &db) const
Return a specified DB xref.
Definition: Seq_feat.cpp:415
Seq-loc iterator class – iterates all intervals from a seq-loc in the correct order.
Definition: Seq_loc.hpp:453
Seq-loc iterator class – iterates all intervals from a seq-loc in the correct order.
Definition: Seq_loc.hpp:593
CSeq_loc_Mapper –.
ICoordMapper interface for converting location between two coordinate systems.
vector< TSeqRange > TIntervals
File Description:
void erase(iterator pos)
Definition: map.hpp:167
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
const_iterator end() const
Definition: map.hpp:152
iterator_bool insert(const value_type &val)
Definition: map.hpp:165
bool empty() const
Definition: map.hpp:149
const_iterator find(const key_type &key) const
Definition: map.hpp:153
Definition: map.hpp:338
bool empty() const
Definition: set.hpp:133
static bool s_HasCDS(const CLinkedFeature &linked_feat)
static bool s_HasFeatXref(const CSeq_feat &feat, CSeqFeatData_Base::E_Choice choice)
USING_SCOPE(objects)
static const char * kGeneByLocUrl
map< int, int > TId2Wt
static bool s_IsGnomonModel(const CSeq_feat &feat)
static const float kMinScaleForMapping
Definition: feature_ds.cpp:85
static const char * kUnsortedGroupName
Definition: feature_ds.cpp:82
static bool s_HasTag(const CSeq_feat &feat, const set< string > &tags)
static bool s_IsSelect(const CLinkedFeature &feat)
static const size_t kMaxChildNum
Definition: feature_ds.cpp:78
static const int kMaxObjNum
Definition: feature_ds.cpp:75
static bool s_IsCCDS(const CLinkedFeature &linked_feat)
bool s_GetGeneWeight(TId2Wt &genes, TGi gi, const TSeqRange &r, size_t retmax)
static const float kSeqZoomLevel
Definition: feature_ds.cpp:80
ELinkedFeatDisplay
@ eLFD_Default
@ eLFD_Expandable
@ eLFD_ParentHidden
@ eLFD_Hidden
static const struct name_t names[]
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static int type
Definition: getdata.c:31
static char tmp[3200]
Definition: utf8.c:42
int offset
Definition: replacements.h:160
static FILE * f
Definition: readconf.c:23
char data[12]
Definition: iconv.c:80
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define NULL
Definition: ncbistd.hpp:225
@ fHTTP_AutoReconnect
See HTTP_CreateConnectorEx()
#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
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:342
static TMappingInfo GetMappingInfoFromLocation(const objects::CSeq_loc &feat_loc, const objects::CSeq_id &product_id, const int feat_offset=0)
Definition: utils.cpp:2200
static TMappingInfo GetRnaMappingInfo(const objects::CSeq_loc &feat_loc, const objects::CMappedFeat &feat, const objects::CBioseq_Handle &handle)
Helper function to generate mapping info between the specified product sequence and genomic sequence ...
Definition: utils.cpp:1901
const objects::CSeq_feat & GetFeature() const
Definition: utils.hpp:87
static bool LinkFeatures(CLinkedFeature::TLinkedFeats &feats, TFeatLinkingMode mode=1, ISeqTaskProgressCallback *p_cb=NULL)
Link features into a hierarchical list.
Definition: utils.cpp:453
static objects::SAnnotSelector GetAnnotSelector(TAnnotFlags flags=0)
request an annotation selector for a given type
Definition: utils.cpp:168
list< CRef< CLinkedFeature > > TLinkedFeats
Definition: utils.hpp:80
static TMappingInfo GetCdsMappingInfoFromRna(const TMappingInfo &rna_mapping_info, const objects::CSeq_feat &rna_feat, const objects::CMappedFeat &mapped_cds_feat, const objects::CSeq_loc &feat_loc, objects::CScope &scope, const int feat_offset=0)
Derive the CDS feature mapping information based on its parent RNA feature mapping info.
Definition: utils.cpp:2037
static bool IsCrossOrigin(const objects::CSeq_loc &loc)
static string GetAnnotName(const objects::CSeq_annot_Handle &annot_handle)
static CRef< objects::CSeq_loc > MixLocToLoc(const objects::CSeq_loc &mix_loc, const objects::CBioseq_Handle &handle)
Create a new seq-loc with a unique seq-id from a "mixed" loc.
Definition: utils.cpp:662
static const string & GetUnnamedAnnot()
Get the commonly used symbol representing a unnnamed annotation.
Definition: utils.hpp:534
static bool IsSameStrands(const objects::CSeq_loc &loc)
Definition: utils.cpp:949
static void SetAnnot(objects::SAnnotSelector &sel, const string &annot)
help function for setting up an annotation.
Definition: utils.cpp:321
vector< TMappedInt > TMappingInfo
Definition: utils.hpp:165
const TLinkedFeats & GetChildren() const
Definition: utils.hpp:89
static void SetResolveDepth(objects::SAnnotSelector &sel, bool adaptive, int depth=-1)
help function for setting selector resolve depth.
Definition: utils.cpp:406
GLdouble TModelUnit
Definition: gltypes.hpp:48
CGlPoint< TModelUnit > TModelPoint
Definition: gltypes.hpp:51
virtual bool IsCanceled() const override
virtual void AddRange(TSeqRange range, CntType score=1, bool expand=false)
EJobState
Job states (describe FSM)
Definition: app_job.hpp:86
@ eUnknown
Definition: app_popup.hpp:72
@ eCanceled
Definition: app_job.hpp:91
@ eCompleted
Definition: app_job.hpp:89
@ eFailed
Definition: app_job.hpp:90
@ eContent
Definition: label.hpp:62
@ eSerial_AsnBinary
ASN.1 binary.
Definition: serialdef.hpp:74
bool Match(const CSeq_id &sid2) const
Match() - TRUE if SeqIds are equivalent.
Definition: Seq_id.hpp:1065
string GetLabel(const CSeq_id &id)
TGi GetGi(void) const
CRef< CSeq_loc > MakeSeq_loc(EMakeType make_type=eMake_CompactType) const
return constructed CSeq_loc with all changes
Definition: Seq_loc.cpp:2946
void Delete(void)
Delete current element, and make iterator to point to the next element.
Definition: Seq_loc.cpp:2724
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
TRange GetTotalRange(void) const
Definition: Seq_loc.hpp:913
CConstRef< CSeq_loc > GetRangeAsSeq_loc(void) const
Get seq-loc for the current iterator position.
Definition: Seq_loc.cpp:2585
void SetInt(TInt &v)
Definition: Seq_loc.hpp:983
const CSeq_id * GetId(void) const
Get the id of the location return NULL if has multiple ids or no id at all.
Definition: Seq_loc.hpp:941
TRange GetRange(void) const
Get the range.
Definition: Seq_loc.hpp:1042
const CSeq_id & GetSeq_id(void) const
Get seq_id of the current location.
Definition: Seq_loc.hpp:1028
static CObjectIStream * Open(ESerialDataFormat format, CNcbiIstream &inStream, bool deleteInStream)
Create serial object reader and attach it to an input stream.
Definition: objistr.cpp:195
@ fFGL_Content
Include its content if there is any.
Definition: feature.hpp:73
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,...
ENa_strand GetStrand(const CSeq_loc &loc, CScope *scope=0)
Returns eNa_strand_unknown if multiple Bioseqs in loc Returns eNa_strand_other if multiple strands in...
sequence::ECompare Compare(const CSeq_loc &loc1, const CSeq_loc &loc2, CScope *scope)
Returns the sequence::ECompare containment relationship between CSeq_locs.
@ fCompareAll
@ fComparePositional
Use positional coordinates (ignore strands) when looking for abutting locations.
@ eNoOverlap
CSeq_locs do not overlap or abut.
@ eGetId_ForceGi
return only a gi-based seq-id
Definition: sequence.hpp:99
CRef< CSeq_loc > Map(const CSeq_loc &src_loc)
Map seq-loc.
const CSeq_annot_Handle & GetAnnot(void) const
Get handle to seq-annot for this feature.
const CSeqFeatData & GetData(void) const
bool IsSetProduct(void) const
CSeqFeatData::ESubtype GetFeatSubtype(void) const
SAnnotSelector & SetFeatType(TFeatType type)
Set feature type (also set annotation type to feat)
vector< CAnnotName > TAnnotsNames
Object manager recognizes several fields of Seq-annot as annot name.
const CSeq_loc & GetLocation(void) const
const CSeq_feat & GetOriginalFeature(void) const
Get original feature with unmapped location/product.
SAnnotSelector & SetCollectNames(bool value=true)
Collect available annot names rather than annots.
SAnnotSelector & IncludeFeatType(TFeatType type)
Include feature type in the search.
const CSeq_loc & GetProduct(void) const
TObjectType * GetNCPointerOrNull(void) const THROWS_NONE
Get pointer value.
Definition: ncbiobj.hpp:1162
TObjectType * GetNCPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1174
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
TObjectType & GetObject(void)
Get object.
Definition: ncbiobj.hpp:1011
position_type GetLength(void) const
Definition: range.hpp:158
TThisType & SetToOpen(position_type toOpen)
Definition: range.hpp:175
#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 SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
Definition: ncbistr.cpp:2984
#define NPOS
Definition: ncbistr.hpp:133
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5078
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5347
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 string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string.
Definition: ncbistr.cpp:3177
unsigned int usec
microseconds (modulo 1,000,000)
Definition: ncbi_types.h:78
unsigned int sec
seconds
Definition: ncbi_types.h:77
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
list< CRef< CEntrez2_docsum > > TList
const TStr & GetStr(void) const
Get the variant data.
bool IsSetData(void) const
the object itself Check if a value has been assigned to Data data member.
bool IsStr(void) const
Check if variant Str is selected.
Definition: Object_id_.hpp:291
bool IsSetType(void) const
type of object within class Check if a value has been assigned to Type data member.
bool IsLim(void) const
Check if variant Lim is selected.
Definition: Int_fuzz_.hpp:636
const TTag & GetTag(void) const
Get the Tag member data.
Definition: Dbtag_.hpp:267
bool IsId(void) const
Check if variant Id is selected.
Definition: Object_id_.hpp:264
const TData & GetData(void) const
Get the Data member data.
TLim GetLim(void) const
Get the variant data.
Definition: Int_fuzz_.hpp:642
bool IsStr(void) const
Check if variant Str is selected.
bool IsSetLabel(void) const
field label Check if a value has been assigned to Label data member.
const TStr & GetStr(void) const
Get the variant data.
Definition: Object_id_.hpp:297
const TData & GetData(void) const
Get the Data member data.
const TObject & GetObject(void) const
Get the variant data.
const TLabel & GetLabel(void) const
Get the Label member data.
const TType & GetType(void) const
Get the Type member data.
bool IsObject(void) const
Check if variant Object is selected.
bool IsSetData(void) const
Check if a value has been assigned to Data data member.
vector< CRef< CUser_field > > TData
TId GetId(void) const
Get the variant data.
Definition: Object_id_.hpp:270
@ eLim_tl
space to left of position
Definition: Int_fuzz_.hpp:214
list< CRef< CGBL_Gene > > TGenes
Definition: GBL_Data_.hpp:91
const TData & GetData(void) const
Get the variant data.
Definition: GBL_Reply_.cpp:103
bool IsError(void) const
Check if variant Error is selected.
Definition: GBL_Reply_.hpp:270
const TError & GetError(void) const
Get the variant data.
Definition: GBL_Reply_.hpp:276
vector< CRef< CDbtag > > TDbxref
Definition: Seq_feat_.hpp:123
bool IsSetQual(void) const
qualifiers Check if a value has been assigned to Qual data member.
Definition: Seq_feat_.hpp:1135
E_Choice Which(void) const
Which variant is currently selected.
bool IsSetExt(void) const
user defined structure extension Check if a value has been assigned to Ext data member.
Definition: Seq_feat_.hpp:1207
bool IsCdregion(void) const
Check if variant Cdregion is selected.
const TQual & GetQual(void) const
Get the Qual member data.
Definition: Seq_feat_.hpp:1147
E_Choice
Choice variants.
bool IsGene(void) const
Check if variant Gene is selected.
TFrame GetFrame(void) const
Get the Frame member data.
Definition: Cdregion_.hpp:534
const TData & GetData(void) const
Get the Data member data.
Definition: Seq_feat_.hpp:925
const TDbxref & GetDbxref(void) const
Get the Dbxref member data.
Definition: Seq_feat_.hpp:1333
const TCdregion & GetCdregion(void) const
Get the variant data.
TPseudo GetPseudo(void) const
Get the Pseudo member data.
Definition: Seq_feat_.hpp:1365
bool IsSetPseudo(void) const
annotated on pseudogene? Check if a value has been assigned to Pseudo data member.
Definition: Seq_feat_.hpp:1346
const TXref & GetXref(void) const
Get the Xref member data.
Definition: Seq_feat_.hpp:1308
vector< CRef< CSeqFeatXref > > TXref
Definition: Seq_feat_.hpp:122
bool IsSetDbxref(void) const
support for xref to other databases Check if a value has been assigned to Dbxref data member.
Definition: Seq_feat_.hpp:1321
const TExt & GetExt(void) const
Get the Ext member data.
Definition: Seq_feat_.hpp:1219
bool IsRna(void) const
Check if variant Rna is selected.
bool IsSetFrame(void) const
Check if a value has been assigned to Frame data member.
Definition: Cdregion_.hpp:509
bool IsMix(void) const
Check if variant Mix is selected.
Definition: Seq_loc_.hpp:552
ENa_strand
strand of nucleic acid
Definition: Na_strand_.hpp:64
const TPnt & GetPnt(void) const
Get the variant data.
Definition: Seq_loc_.cpp:238
TPoint GetPoint(void) const
Get the Point member data.
Definition: Seq_point_.hpp:303
list< CRef< CSeq_loc > > Tdata
const TFuzz & GetFuzz(void) const
Get the Fuzz member data.
Definition: Seq_point_.hpp:420
E_Choice Which(void) const
Which variant is currently selected.
Definition: Seq_loc_.hpp:475
const Tdata & Get(void) const
Get the member data.
bool CanGetFuzz(void) const
Check if it is safe to call GetFuzz method.
Definition: Seq_point_.hpp:414
const TMix & GetMix(void) const
Get the variant data.
Definition: Seq_loc_.cpp:282
bool IsPnt(void) const
Check if variant Pnt is selected.
Definition: Seq_loc_.hpp:540
@ eNa_strand_minus
Definition: Na_strand_.hpp:67
@ e_Null
not placed
Definition: Seq_loc_.hpp:98
@ e_Empty
to NULL one Seq-id in a collection
Definition: Seq_loc_.hpp:99
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
n font weight
int len
static MDB_envinfo info
Definition: mdb_load.c:37
range(_Ty, _Ty) -> range< _Ty >
constexpr auto sort(_Init &&init)
const struct ncbi::grid::netcache::search::fields::SIZE size
const char * tag
T max(T x_, T y_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
struct named_group named_group
vector< SFeatBatchJobRequest > TFeatBatchJobRequests
#define row(bind, expected)
Definition: string_bind.c:73
SAnnotSelector –.
CSGFeatureJob implementation.
Definition: feature_ds.cpp:624
bool operator()(const CSGFeatureJob::SLandmarkFeat &f1, const CSGFeatureJob::SLandmarkFeat &f2) const
Definition: feature_ds.cpp:625
bool operator()(const CSGFeatureJob::SLandmarkFeat &f1, const CSGFeatureJob::SLandmarkFeat &f2) const
Definition: feature_ds.cpp:634
Timeout structure.
Definition: ncbi_types.h:76
TEMPLATE STRUCT max.
Definition: density_map.hpp:88
TEMPLATE STRUCT max.
Definition: density_map.hpp:70
Definition: type.c:6
#define _ASSERT
else result
Definition: token2.c:20
Modified on Fri Sep 20 14:57:35 2024 by modify_doxy.py rev. 669887