gather_items.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:40k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: gather_items.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:44:32  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: gather_items.cpp,v 1000.2 2004/06/01 19:44:32 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Aaron Ucko, NCBI
  35. *          Mati Shomrat, NCBI
  36. *
  37. * File Description:
  38. *   
  39. *
  40. * ===========================================================================
  41. */
  42. #include <ncbi_pch.hpp>
  43. #include <corelib/ncbistd.hpp>
  44. #include <objects/seq/Bioseq.hpp>
  45. #include <objects/seq/Seq_inst.hpp>
  46. #include <objects/seq/Seq_hist.hpp>
  47. #include <objects/seq/Seq_hist_rec.hpp>
  48. #include <objects/seq/Seqdesc.hpp>
  49. #include <objects/seq/Seq_descr.hpp>
  50. #include <objects/seqset/Seq_entry.hpp>
  51. #include <objects/general/User_object.hpp>
  52. #include <objects/general/User_field.hpp>
  53. #include <objects/general/Object_id.hpp>
  54. #include <objects/seqblock/GB_block.hpp>
  55. #include <objects/seqfeat/BioSource.hpp>
  56. #include <objmgr/scope.hpp>
  57. #include <objmgr/bioseq_handle.hpp>
  58. #include <objmgr/bioseq_ci.hpp>
  59. #include <objmgr/seq_entry_handle.hpp>
  60. #include <objmgr/seq_entry_ci.hpp>
  61. #include <objmgr/seq_map.hpp>
  62. #include <objmgr/seqdesc_ci.hpp>
  63. #include <objmgr/feat_ci.hpp>
  64. #include <objmgr/util/sequence.hpp>
  65. #include <objmgr/seq_loc_mapper.hpp>
  66. #include <algorithm>
  67. #include <objtools/format/item_ostream.hpp>
  68. #include <objtools/format/flat_expt.hpp>
  69. #include <objtools/format/items/locus_item.hpp>
  70. #include <objtools/format/items/defline_item.hpp>
  71. #include <objtools/format/items/accession_item.hpp>
  72. #include <objtools/format/items/version_item.hpp>
  73. #include <objtools/format/items/keywords_item.hpp>
  74. #include <objtools/format/items/source_item.hpp>
  75. #include <objtools/format/items/reference_item.hpp>
  76. #include <objtools/format/items/comment_item.hpp>
  77. #include <objtools/format/items/basecount_item.hpp>
  78. #include <objtools/format/items/sequence_item.hpp>
  79. #include <objtools/format/items/feature_item.hpp>
  80. #include <objtools/format/items/segment_item.hpp>
  81. #include <objtools/format/items/ctrl_items.hpp>
  82. #include <objtools/format/gather_items.hpp>
  83. #include <objtools/format/genbank_gather.hpp>
  84. #include <objtools/format/embl_gather.hpp>
  85. #include <objtools/format/gff_gather.hpp>
  86. #include <objtools/format/ftable_gather.hpp>
  87. #include <objtools/format/context.hpp>
  88. #include "utils.hpp"
  89. BEGIN_NCBI_SCOPE
  90. BEGIN_SCOPE(objects)
  91. USING_SCOPE(sequence);
  92. /////////////////////////////////////////////////////////////////////////////
  93. //
  94. // Public:
  95. // "virtual constructor"
  96. CFlatGatherer* CFlatGatherer::New(CFlatFileConfig::TFormat format)
  97. {
  98.     switch ( format ) {
  99.     case CFlatFileConfig::eFormat_GenBank:
  100.     case CFlatFileConfig::eFormat_GBSeq:
  101.         //case CFlatFileGenerator<>::eFormat_Index:
  102.         return new CGenbankGatherer;
  103.         
  104.     case CFlatFileConfig::eFormat_EMBL:
  105.         return new CEmblGatherer;
  106.     case CFlatFileConfig::eFormat_GFF:
  107.         return new CGFFGatherer;
  108.     
  109.     case CFlatFileConfig::eFormat_FTable:
  110.         return new CFtableGatherer;
  111.     case CFlatFileConfig::eFormat_DDBJ:
  112.     default:
  113.         NCBI_THROW(CFlatException, eNotSupported, 
  114.             "This format is currently not supported");
  115.     }
  116.     return 0;
  117. }
  118. void CFlatGatherer::Gather(CFlatFileContext& ctx, CFlatItemOStream& os) const
  119. {
  120.     m_ItemOS.Reset(&os);
  121.     m_Context.Reset(&ctx);
  122.     os << new CStartItem();
  123.     x_GatherSeqEntry(ctx.GetEntry());
  124.     os << new CEndItem();
  125. }
  126. CFlatGatherer::~CFlatGatherer(void)
  127. {
  128. }
  129. /////////////////////////////////////////////////////////////////////////////
  130. //
  131. // Protected:
  132. void CFlatGatherer::x_GatherSeqEntry(const CSeq_entry_Handle& entry) const
  133. {
  134.     if ( entry.IsSet()  &&  entry.GetSet().IsSetClass() ) {
  135.         CBioseq_set::TClass clss = entry.GetSet().GetClass();
  136.         if ( clss == CBioseq_set::eClass_genbank  ||
  137.              clss == CBioseq_set::eClass_mut_set  ||
  138.              clss == CBioseq_set::eClass_pop_set  ||
  139.              clss == CBioseq_set::eClass_phy_set  ||
  140.              clss == CBioseq_set::eClass_eco_set  ||
  141.              clss == CBioseq_set::eClass_wgs_set  ||
  142.              clss == CBioseq_set::eClass_gen_prod_set ) {
  143.             for ( CSeq_entry_CI it(entry); it; ++it ) {
  144.                 x_GatherSeqEntry(*it);
  145.             }
  146.             return;
  147.         }
  148.     }
  149.     // visit each bioseq in the entry (excluding segments)
  150.     CBioseq_CI seq_iter(entry, CSeq_inst::eMol_not_set,
  151.         CBioseq_CI::eLevel_Mains);
  152.     for ( ; seq_iter; ++seq_iter ) {
  153.         if ( x_DisplayBioseq(entry, *seq_iter) ) {
  154.             x_GatherBioseq(*seq_iter);
  155.         }
  156.     }
  157. bool CFlatGatherer::x_DisplayBioseq
  158. (const CSeq_entry_Handle& entry,
  159.  const CBioseq_Handle& seq) const
  160. {
  161.     const CFlatFileConfig& cfg = Config();
  162.     const CSeq_id& id = GetId(seq, eGetId_Best);
  163.     if ( id.IsLocal()  &&  cfg.SuppressLocalId() ) {
  164.         return false;
  165.     }
  166.     if ( (CSeq_inst::IsNa(seq.GetInst_Mol())  &&  cfg.IsViewNuc())  ||
  167.          (CSeq_inst::IsAa(seq.GetInst_Mol())  &&  cfg.IsViewProt()) ) {
  168.         return true;
  169.     }
  170.     return false;
  171. }
  172. bool s_IsSegmented(const CBioseq_Handle& seq)
  173. {
  174.     return seq  &&
  175.            seq.IsSetInst()  &&
  176.            seq.IsSetInst_Repr()  &&
  177.            seq.GetInst_Repr() == CSeq_inst::eRepr_seg;
  178. }
  179. // a defualt implementation for GenBank /  DDBJ formats
  180. void CFlatGatherer::x_GatherBioseq(const CBioseq_Handle& seq) const
  181. {
  182.     bool segmented = s_IsSegmented(seq);
  183.     const CFlatFileConfig& cfg = Config();
  184.     // Do multiple sections (segmented style) if:
  185.     // a. the bioseq is segmented
  186.     // b. style is normal or segmented (not master)
  187.     // c. user didn't specify a location
  188.     // d. not FTable format
  189.     if ( segmented                                        &&
  190.          (cfg.IsStyleNormal()  ||  cfg.IsStyleSegment())  &&
  191.          (m_Context->GetLocation() == 0)                  &&
  192.          !cfg.IsFormatFTable() ) {
  193.         x_DoMultipleSections(seq);
  194.     } else {
  195.         // display as a single bioseq (single section)
  196.         m_Current.Reset(new CBioseqContext(seq, *m_Context));
  197.         m_Context->AddSection(m_Current);
  198.         x_DoSingleSection(*m_Current);
  199.     }   
  200. }
  201. void CFlatGatherer::x_DoMultipleSections(const CBioseq_Handle& seq) const
  202. {
  203.     CRef<CMasterContext> mctx(new CMasterContext(seq));
  204.     CScope* scope = &seq.GetScope();
  205.     const CSeqMap& seqmap = seq.GetSeqMap();
  206.     CSeqMap::TSegment_CI it = seqmap.BeginResolved(scope, 1, CSeqMap::fFindRef);
  207.     while ( it ) {
  208.         CSeq_id_Handle id = it.GetRefSeqid();
  209.         CBioseq_Handle part = scope->GetBioseqHandleFromTSE(id, seq);
  210.         if ( part ) {
  211.             m_Current.Reset(new CBioseqContext(part, *m_Context, mctx));
  212.             m_Context->AddSection(m_Current);
  213.             x_DoSingleSection(*m_Current);
  214.         }
  215.         ++it;
  216.     }
  217. }
  218.     
  219. /////////////////////////////////////////////////////////////////////////////
  220. //
  221. // REFERENCES
  222. bool s_FilterPubdesc(const CPubdesc& pubdesc, CBioseqContext& ctx)
  223. {
  224.     if ( pubdesc.CanGetComment() ) {
  225.         const string& comment = pubdesc.GetComment();
  226.         bool is_gene_rif = NStr::StartsWith(comment, "GeneRIF", NStr::eNocase);
  227.         const CFlatFileConfig& cfg = ctx.Config();
  228.         if ( (cfg.HideGeneRIFs()  &&  is_gene_rif)  ||
  229.              ((cfg.OnlyGeneRIFs()  ||  cfg.LatestGeneRIFs())  &&  !is_gene_rif) ) {
  230.             return true;
  231.         }
  232.     }
  233.     return false;
  234. }
  235. void CFlatGatherer::x_GatherReferences(void) const
  236. {
  237.     CBioseqContext::TReferences& refs = m_Current->SetReferences();
  238.     // gather references from descriptors
  239.     for (CSeqdesc_CI it(m_Current->GetHandle(), CSeqdesc::e_Pub); it; ++it) {
  240.         const CPubdesc& pubdesc = it->GetPub();
  241.         if ( s_FilterPubdesc(pubdesc, *m_Current) ) {
  242.             continue;
  243.         }
  244.         
  245.         refs.push_back(CBioseqContext::TRef(new CReferenceItem(*it, *m_Current)));
  246.     }
  247.     // gather references from features
  248.     SAnnotSelector sel(CSeqFeatData::e_Pub);
  249.     sel.SetCombineMethod(SAnnotSelector::eCombine_All);
  250.     CFeat_CI it(m_Current->GetScope(), m_Current->GetLocation(), sel);
  251.     for ( ; it; ++it) {
  252.         refs.push_back(CBioseqContext::TRef(new CReferenceItem(it->GetData().GetPub(),
  253.                                         *m_Current, &it->GetLocation())));
  254.     }
  255.     CReferenceItem::Rearrange(refs, *m_Current);
  256.     ITERATE (CBioseqContext::TReferences, ref, refs) {
  257.         *m_ItemOS << *ref;
  258.     }
  259. }
  260. /////////////////////////////////////////////////////////////////////////////
  261. //
  262. // COMMENTS
  263. void CFlatGatherer::x_GatherComments(void) const
  264. {
  265.     CBioseqContext& ctx = *m_Current;
  266.     // Gather comments related to the seq-id
  267.     x_IdComments(ctx);
  268.     x_RefSeqComments(ctx);
  269.     if ( CCommentItem::NsAreGaps(ctx.GetHandle(), ctx) ) {
  270.         x_AddComment(new CCommentItem(CCommentItem::kNsAreGaps, ctx));
  271.     }
  272.     x_HistoryComments(ctx);
  273.     x_WGSComment(ctx);
  274.     if ( ctx.ShowGBBSource() ) {
  275.         x_GBBSourceComment(ctx);
  276.     }
  277.     x_DescComments(ctx);
  278.     x_MaplocComments(ctx);
  279.     x_RegionComments(ctx);
  280.     x_HTGSComments(ctx);
  281.     x_FeatComments(ctx);
  282.     x_FlushComments();
  283. }
  284. void CFlatGatherer::x_AddComment(CCommentItem* comment) const
  285. {
  286.     CRef<CCommentItem> com(comment);
  287.     if ( !com->Skip() ) {
  288.         m_Comments.push_back(com);
  289.     }
  290. }
  291. void CFlatGatherer::x_AddGSDBComment
  292. (const CDbtag& dbtag,
  293.  CBioseqContext& ctx) const
  294. {
  295.     CRef<CCommentItem> gsdb_comment(new CGsdbComment(dbtag, ctx));
  296.     if ( !gsdb_comment->Skip() ) {
  297.         m_Comments.push_back(gsdb_comment);
  298.     }
  299. }
  300. void CFlatGatherer::x_FlushComments(void) const
  301. {
  302.     if ( m_Comments.empty() ) {
  303.         return;
  304.     }
  305.     // add a period to the last comment (if not local id)
  306.     if ( dynamic_cast<CLocalIdComment*>(&*m_Comments.back()) == 0 ) {
  307.         m_Comments.back()->AddPeriod();
  308.     }
  309.     
  310.     // add a period to a GSDB comment (if exist and not last)
  311.     TCommentVec::iterator last = m_Comments.end();
  312.     --last;
  313.     NON_CONST_ITERATE (TCommentVec, it, m_Comments) {
  314.         CGsdbComment* gsdb = dynamic_cast<CGsdbComment*>(it->GetPointerOrNull());
  315.         if ( gsdb != 0   &&  it != last ) {
  316.             gsdb->AddPeriod();
  317.         }
  318.         *m_ItemOS << *it;
  319.     }
  320.     m_Comments.clear();
  321. }
  322. string s_GetGenomeBuildNumber(const CBioseq_Handle& bsh)
  323. {
  324.     for (CSeqdesc_CI it(bsh, CSeqdesc::e_User);  it;  ++it) {
  325.         const CUser_object& uo = it->GetUser();
  326.         if ( uo.IsSetType()  &&  uo.GetType().IsStr()  &&
  327.              uo.GetType().GetStr() == "GenomeBuild" ) {
  328.             if ( uo.HasField("NcbiAnnotation") ) {
  329.                 const CUser_field& uf = uo.GetField("NcbiAnnotation");
  330.                 if ( uf.CanGetData()  &&  uf.GetData().IsStr()  &&
  331.                      !uf.GetData().GetStr().empty() ) {
  332.                     return uf.GetData().GetStr();
  333.                 }
  334.             } else if ( uo.HasField("Annotation") ) {
  335.                 const CUser_field& uf = uo.GetField("Annotation");
  336.                 if ( uf.CanGetData()  &&  uf.GetData().IsStr()  &&
  337.                      !uf.GetData().GetStr().empty() ) {
  338.                     static const string prefix = "NCBI build ";
  339.                     if ( NStr::StartsWith(uf.GetData().GetStr(), prefix) ) {
  340.                         return uf.GetData().GetStr().substr(prefix.length());
  341.                     }
  342.                 }
  343.             }
  344.         }
  345.     }
  346.     return kEmptyStr;
  347. }
  348. bool s_HasRefTrackStatus(const CBioseq_Handle& bsh) {
  349.     for (CSeqdesc_CI it(bsh, CSeqdesc::e_User);  it;  ++it) {
  350.         CCommentItem::TRefTrackStatus status = 
  351.             CCommentItem::GetRefTrackStatus(it->GetUser());
  352.         if ( status != CCommentItem::eRefTrackStatus_Unknown ) { 
  353.             return true;
  354.         }
  355.     }
  356.     return false;
  357. }
  358. void CFlatGatherer::x_IdComments(CBioseqContext& ctx) const
  359. {
  360.     const CObject_id* local_id = 0;
  361.     string genome_build_number = s_GetGenomeBuildNumber(ctx.GetHandle());
  362.     bool has_ref_track_status = s_HasRefTrackStatus(ctx.GetHandle());
  363.     ITERATE( CBioseq::TId, id_iter, ctx.GetBioseqIds() ) {
  364.         const CSeq_id& id = **id_iter;
  365.         switch ( id.Which() ) {
  366.         case CSeq_id::e_Other:
  367.             {{
  368.                 if ( ctx.IsRSCompleteGenomic() ) {
  369.                     if ( !genome_build_number.empty() ) {
  370.                         x_AddComment(new CGenomeAnnotComment(ctx, genome_build_number));
  371.                     }
  372.                 }
  373.                 if ( ctx.IsRSContig()  ||  ctx.IsRSIntermedWGS() ) {
  374.                     if ( !has_ref_track_status ) {
  375.                         x_AddComment(new CGenomeAnnotComment(ctx, genome_build_number));
  376.                     }
  377.                 }
  378.                 if ( ctx.IsRSPredictedProtein()  ||
  379.                      ctx.IsRSPredictedMRna()     ||
  380.                      ctx.IsRSPredictedNCRna()    ||
  381.                      ctx.IsRSWGSProt() ) {
  382.                     SModelEvidance me;
  383.                     if ( GetModelEvidance(ctx.GetHandle(), me) ) {
  384.                         string str = CCommentItem::GetStringForModelEvidance(me);
  385.                         if ( !str.empty() ) {
  386.                             x_AddComment(new CCommentItem(str, ctx));
  387.                         }
  388.                     }
  389.                 }
  390.             }}
  391.             break;
  392.         case CSeq_id::e_General:
  393.             {{
  394.                 const CDbtag& dbtag = id.GetGeneral();
  395.                 if ( dbtag.CanGetDb()  &&  dbtag.GetDb() == "GSDB"  &&
  396.                      dbtag.CanGetTag()  &&  dbtag.GetTag().IsId() ) {
  397.                     x_AddGSDBComment(dbtag, ctx);
  398.                 }
  399.             }}
  400.             break;
  401.         case CSeq_id::e_Local:
  402.             {{
  403.                 local_id = &(id.GetLocal());
  404.             }}
  405.             break;
  406.         default:
  407.             break;
  408.         }
  409.     }
  410.     if ( local_id != 0 ) {
  411.         if ( ctx.IsTPA()  ||  ctx.IsGED() ) {
  412.             if ( ctx.Config().IsModeGBench()  ||  ctx.Config().IsModeDump() ) {
  413.                 x_AddComment(new CLocalIdComment(*local_id, ctx));
  414.             }
  415.         }
  416.     }
  417. }
  418. void CFlatGatherer::x_RefSeqComments(CBioseqContext& ctx) const
  419. {
  420.     bool did_tpa = false, did_ref_track = false, did_genome = false;
  421.     for (CSeqdesc_CI it(ctx.GetHandle(), CSeqdesc::e_User);  it;  ++it) {
  422.         const CUser_object& uo = it->GetUser();
  423.         // TPA
  424.         {{
  425.             if ( !did_tpa ) {
  426.                 string str = CCommentItem::GetStringForTPA(uo, ctx);
  427.                 if ( !str.empty() ) {
  428.                     x_AddComment(new CCommentItem(str, ctx, &uo));
  429.                     did_tpa = true;
  430.                 }
  431.             }
  432.         }}
  433.         // BankIt
  434.         {{
  435.             if ( !ctx.Config().HideBankItComment() ) {
  436.                 string str = CCommentItem::GetStringForBankIt(uo);
  437.                 if ( !str.empty() ) {
  438.                     x_AddComment(new CCommentItem(str, ctx, &uo));
  439.                 }
  440.             }
  441.         }}
  442.         // RefTrack
  443.         {{
  444.             if ( !did_ref_track ) {
  445.                 string str = CCommentItem::GetStringForRefTrack(uo);
  446.                 if ( !str.empty() ) {
  447.                     x_AddComment(new CCommentItem(str, ctx, &uo));
  448.                     did_ref_track = true;
  449.                 }
  450.             }
  451.         }}
  452.         // Genome
  453.         {{
  454.             if ( !did_genome ) {
  455.                 // !!! Not implememnted in the C version. should it be?
  456.             }
  457.         }}
  458.     }
  459. }
  460. void CFlatGatherer::x_HistoryComments(CBioseqContext& ctx) const
  461. {
  462.     const CBioseq_Handle& seq = ctx.GetHandle();
  463.     if ( !seq.IsSetInst_Hist() ) {
  464.         return;
  465.     }
  466.     const CSeq_hist& hist = seq.GetInst_Hist();
  467.     if ( hist.CanGetReplaced_by() ) {
  468.         const CSeq_hist::TReplaced_by& r = hist.GetReplaced_by();
  469.         if ( r.CanGetDate()  &&  !r.GetIds().empty() ) {
  470.             x_AddComment(new CHistComment(CHistComment::eReplaced_by,
  471.                 hist, ctx));
  472.         }
  473.     }
  474.     if ( hist.IsSetReplaces()  &&  !ctx.Config().IsModeGBench() ) {
  475.         const CSeq_hist::TReplaces& r = hist.GetReplaces();
  476.         if ( r.CanGetDate()  &&  !r.GetIds().empty() ) {
  477.             x_AddComment(new CHistComment(CHistComment::eReplaces,
  478.                 hist, ctx));
  479.         }
  480.     }
  481. }
  482. void CFlatGatherer::x_WGSComment(CBioseqContext& ctx) const
  483. {
  484.     if ( !ctx.IsWGSMaster()  ||  ctx.GetWGSMasterName().empty() ) {
  485.         return;
  486.     }
  487.     if ( ctx.GetTech() == CMolInfo::eTech_wgs ) {
  488.         string str = CCommentItem::GetStringForWGS(ctx);
  489.         if ( !str.empty() ) {
  490.             x_AddComment(new CCommentItem(str, ctx));
  491.         }
  492.     }
  493. }
  494. void CFlatGatherer::x_GBBSourceComment(CBioseqContext& ctx) const
  495. {
  496.     _ASSERT(ctx.ShowGBBSource());
  497.     for (CSeqdesc_CI it(ctx.GetHandle(), CSeqdesc::e_Genbank); it; ++it) {
  498.         const CGB_block& gbb = it->GetGenbank();
  499.         if ( gbb.CanGetSource()  &&  !gbb.GetSource().empty() ) {
  500.             x_AddComment(new CCommentItem(
  501.                 "Original source text: " + gbb.GetSource(),
  502.                 ctx,
  503.                 &(*it)));
  504.         }
  505.     }
  506. }
  507. void CFlatGatherer::x_DescComments(CBioseqContext& ctx) const
  508. {
  509.     for (CSeqdesc_CI it(ctx.GetHandle(), CSeqdesc::e_Comment); it; ++it) {
  510.         x_AddComment(new CCommentItem(*it, ctx));
  511.     }
  512. }
  513. void CFlatGatherer::x_MaplocComments(CBioseqContext& ctx) const
  514. {
  515.     for (CSeqdesc_CI it(ctx.GetHandle(), CSeqdesc::e_Maploc); it; ++it) {
  516.         x_AddComment(new CCommentItem(*it, ctx));
  517.     }
  518. }
  519. void CFlatGatherer::x_RegionComments(CBioseqContext& ctx) const
  520. {
  521.     for (CSeqdesc_CI it(ctx.GetHandle(), CSeqdesc::e_Region); it; ++it) {
  522.         x_AddComment(new CCommentItem(*it, ctx));
  523.     }
  524. }
  525. void CFlatGatherer::x_HTGSComments(CBioseqContext& ctx) const
  526. {
  527.     CSeqdesc_CI desc(ctx.GetHandle(), CSeqdesc::e_Molinfo);
  528.     if ( !desc ) {
  529.         return;
  530.     }
  531.     const CMolInfo& mi = *ctx.GetMolinfo();
  532.     if ( ctx.IsRefSeq()  &&  
  533.          mi.GetCompleteness() != CMolInfo::eCompleteness_unknown ) {
  534.         string str = CCommentItem::GetStringForMolinfo(mi, ctx);
  535.         if ( !str.empty() ) {
  536.             x_AddComment(new CCommentItem(str, ctx, &(*desc)));
  537.         }
  538.     }
  539.     CMolInfo::TTech tech = mi.GetTech();
  540.     if ( tech == CMolInfo::eTech_htgs_0  ||
  541.          tech == CMolInfo::eTech_htgs_1  ||
  542.          tech == CMolInfo::eTech_htgs_2 ) {
  543.         x_AddComment(new CCommentItem(
  544.             CCommentItem::GetStringForHTGS(ctx), ctx, &(*desc)));
  545.     } else {
  546.         const string& tech_str = GetTechString(tech);
  547.         if ( !tech_str.empty() ) {
  548.             x_AddComment(new CCommentItem("Method: " + tech_str, ctx, &(*desc)));
  549.         }
  550.     }
  551. }
  552. void CFlatGatherer::x_FeatComments(CBioseqContext& ctx) const
  553. {
  554.     // !!!
  555. }
  556. /////////////////////////////////////////////////////////////////////////////
  557. //
  558. // SEQUENCE
  559. // We use multiple items to represent the sequence.
  560. void CFlatGatherer::x_GatherSequence(void) const
  561. {
  562.     static const TSeqPos kChunkSize = 2400; // 20 lines
  563.     
  564.     bool first = true;
  565.     TSeqPos size = GetLength(m_Current->GetLocation(), &m_Current->GetScope());
  566.     for ( TSeqPos start = 0; start < size; start += kChunkSize ) {
  567.         TSeqPos end = min(start + kChunkSize, size);
  568.         *m_ItemOS << new CSequenceItem(start, end, first, *m_Current);
  569.         first = false;
  570.     }
  571. }
  572. /////////////////////////////////////////////////////////////////////////////
  573. //
  574. // FEATURES
  575. // source
  576. void CFlatGatherer::x_CollectSourceDescriptors
  577. (const CBioseq_Handle& bh,
  578.  CBioseqContext& ctx,
  579.  TSourceFeatSet& srcs) const
  580. {
  581.     CRef<CSourceFeatureItem> sf;
  582.     CScope* scope = &ctx.GetScope();
  583.     const CSeq_loc& loc = ctx.GetLocation();
  584.     TRange print_range(0, GetLength(loc, scope) - 1);
  585.     for ( CSeqdesc_CI dit(bh, CSeqdesc::e_Source); dit;  ++dit) {
  586.         sf.Reset(new CSourceFeatureItem(dit->GetSource(), print_range, ctx));
  587.         srcs.push_back(sf);
  588.     }
  589.     
  590.     // if segmented collect descriptors from segments
  591.     if ( ctx.IsSegmented() ) {
  592.         CConstRef<CSeqMap> seq_map = CSeqMap::CreateSeqMapForSeq_loc(loc, scope);
  593.               
  594.         // iterate over segments
  595.         CSeqMap_CI smit(seq_map->begin_resolved(scope, 1, CSeqMap::fFindRef));
  596.         for ( ; smit; ++smit ) {
  597.             CBioseq_Handle segh = scope->GetBioseqHandle(smit.GetRefSeqid());
  598.             if ( !segh  ||  !segh.IsSetDescr() ) {
  599.                 continue;
  600.             }
  601.             CRange<TSeqPos> seg_range(smit.GetPosition(), smit.GetEndPosition());
  602.             // collect descriptors only from the segment 
  603.             ITERATE(CBioseq_Handle::TDescr::Tdata, it, segh.GetDescr().Get()) {
  604.                 if ( (*it)->IsSource() ) {
  605.                     sf.Reset(new CSourceFeatureItem((*it)->GetSource(), seg_range, ctx));
  606.                     srcs.push_back(sf);
  607.                 }
  608.             }
  609.         }
  610.     }
  611. }
  612. void CFlatGatherer::x_CollectSourceFeatures
  613. (const CBioseq_Handle& bh,
  614.  const TRange& range,
  615.  CBioseqContext& ctx,
  616.  TSourceFeatSet& srcs) const
  617. {
  618.     SAnnotSelector as;
  619.     as.SetFeatType(CSeqFeatData::e_Biosrc);
  620.     as.SetOverlapIntervals();
  621.     as.SetCombineMethod(SAnnotSelector::eCombine_All);
  622.     as.SetResolveDepth(1);  // in case segmented
  623.     as.SetNoMapping(false);
  624.     for ( CFeat_CI fi(bh, range.GetFrom(), range.GetTo(), as); fi; ++fi ) {
  625.         TSeqPos stop = fi->GetLocation().GetTotalRange().GetTo();
  626.         if ( stop >= range.GetFrom()  &&  stop  <= range.GetTo() ) {
  627.             CRef<CSourceFeatureItem> sf(new CSourceFeatureItem(*fi, ctx));
  628.             srcs.push_back(sf);
  629.         }
  630.     }
  631. }
  632. void CFlatGatherer::x_CollectBioSourcesOnBioseq
  633. (const CBioseq_Handle& bh,
  634.  const TRange& range,
  635.  CBioseqContext& ctx,
  636.  TSourceFeatSet& srcs) const
  637. {
  638.     const CFlatFileConfig& cfg = ctx.Config();
  639.     // collect biosources descriptors on bioseq
  640.     if ( !cfg.IsFormatFTable()  ||  cfg.IsModeDump() ) {
  641.         x_CollectSourceDescriptors(bh, ctx, srcs);
  642.     }
  643.     // collect biosources features on bioseq
  644.     if ( !ctx.DoContigStyle()  ||  cfg.ShowContigSources() ) {
  645.         x_CollectSourceFeatures(bh, range, ctx, srcs);
  646.     }
  647. }
  648. void CFlatGatherer::x_CollectBioSources(TSourceFeatSet& srcs) const
  649. {
  650.     CBioseqContext& ctx = *m_Current;
  651.     CScope* scope = &ctx.GetScope();
  652.     const CFlatFileConfig& cfg = ctx.Config();
  653.     x_CollectBioSourcesOnBioseq(ctx.GetHandle(),
  654.                                 ctx.GetLocation().GetTotalRange(),
  655.                                 ctx,
  656.                                 srcs);
  657.     
  658.     // if protein with no sources, get sources applicable to DNA location of CDS
  659.     if ( srcs.empty()  &&  ctx.IsProt() ) {
  660.         const CSeq_feat* cds = GetCDSForProduct(ctx.GetHandle());
  661.         if ( cds != 0 ) {
  662.             const CSeq_loc& cds_loc = cds->GetLocation();
  663.             x_CollectBioSourcesOnBioseq(
  664.                 scope->GetBioseqHandle(cds_loc),
  665.                 cds_loc.GetTotalRange(),
  666.                 ctx,
  667.                 srcs);
  668.         }
  669.     }
  670.     // if no source found create one (only if not FTable format or Dump mode)
  671.     if ( srcs.empty()  &&  !cfg.IsFormatFTable()  ||  cfg.IsModeDump() ) {
  672.         CRef<CBioSource> bsrc(new CBioSource);
  673.         CRef<CSourceFeatureItem> sf(new CSourceFeatureItem(*bsrc, CRange<TSeqPos>::GetWhole(), ctx));
  674.         srcs.push_back(sf);
  675.     }
  676. }
  677. void CFlatGatherer::x_MergeEqualBioSources(TSourceFeatSet& srcs) const
  678. {
  679.     if ( srcs.size() < 2 ) {
  680.         return;
  681.     }
  682.     // !!! To Do:
  683.     // !!! * sort based on biosource
  684.     // !!! * merge equal biosources (merge locations)
  685. }
  686. void CFlatGatherer::x_SubtractFromFocus(TSourceFeatSet& srcs) const
  687. {
  688.     if ( srcs.size() < 2 ) {
  689.         return;
  690.     }
  691.     // !!! To Do:
  692.     // !!! * implement SeqLocSubtract
  693. }
  694. struct SSortByLoc
  695. {
  696.     bool operator()(const CRef<CSourceFeatureItem>& sfp1,
  697.                     const CRef<CSourceFeatureItem>& sfp2) 
  698.     {
  699.         // descriptor always goes first
  700.         if ( sfp1->WasDesc()  &&  !sfp2->WasDesc() ) {
  701.             return true;
  702.         }
  703.         
  704.         CSeq_loc::TRange range1 = sfp1->GetLoc().GetTotalRange();
  705.         CSeq_loc::TRange range2 = sfp2->GetLoc().GetTotalRange();
  706.         // feature with smallest left extreme is first
  707.         if ( range1.GetFrom() != range2.GetFrom() ) {
  708.             return range1.GetFrom() < range2.GetFrom();
  709.         }
  710.         
  711.         // shortest first (just for flatfile)
  712.         if ( range1.GetToOpen() != range2.GetToOpen() ) {
  713.             return range1.GetToOpen() < range2.GetToOpen();
  714.         }
  715.         
  716.         return false;
  717.     }
  718. };
  719. void CFlatGatherer::x_GatherSourceFeatures(void) const
  720. {
  721.     TSourceFeatSet srcs;
  722.     
  723.     x_CollectBioSources(srcs);
  724.     if ( srcs.empty() ) {
  725.         return;
  726.     }
  727.     x_MergeEqualBioSources(srcs);
  728.     
  729.     // sort by type (descriptor / feature) and location
  730.     sort(srcs.begin(), srcs.end(), SSortByLoc());
  731.     
  732.     // if the descriptor has a focus, subtract out all other source locations.
  733.     if ( srcs.front()->GetSource().IsSetIs_focus() ) {
  734.         x_SubtractFromFocus(srcs);
  735.         // if features completely subtracted descriptor intervals,
  736.         // suppress in release, entrez modes.
  737.         if ( srcs.front()->GetLoc().GetTotalRange().GetLength() == 0  &&
  738.              m_Current->Config().HideEmptySource()  &&  srcs.size() > 1 ) {
  739.             srcs.pop_front();
  740.         }
  741.     }
  742.   
  743.     ITERATE( TSourceFeatSet, it, srcs ) {
  744.         *m_ItemOS << *it;
  745.     }
  746. }
  747. void s_SetSelection(SAnnotSelector& sel, CBioseqContext& ctx)
  748. {
  749.     const CFlatFileConfig& cfg = ctx.Config();
  750.     // set feature types to be collected
  751.     {{
  752.         sel.SetAnnotType(CSeq_annot::C_Data::e_Ftable);
  753.         // source features are collected elsewhere
  754.         sel.ExcludeFeatType(CSeqFeatData::e_Biosrc);
  755.         // pub features are used in the REFERENCES section
  756.         sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_pub);
  757.         // some feature types are always excluded (deprecated?)
  758.         sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_non_std_residue);
  759.         sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_rsite);
  760.         sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_seq);
  761.         // exclude other types based on user flags
  762.         if ( cfg.HideImpFeats() ) {
  763.             sel.ExcludeFeatType(CSeqFeatData::e_Imp);
  764.         }
  765.         if ( cfg.HideRemoteImpFeats() ) {
  766.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_variation);
  767.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_exon);
  768.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_intron);
  769.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_misc_feature);
  770.         }
  771.         if ( cfg.HideSNPFeatures() ) {
  772.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_variation);
  773.         }
  774.         if ( cfg.HideExonFeatures() ) {
  775.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_exon);
  776.         }
  777.         if ( cfg.HideIntronFeatures() ) {
  778.             sel.ExcludeFeatSubtype(CSeqFeatData::eSubtype_intron);
  779.         }
  780.     }}
  781.     sel.SetOverlapType(SAnnotSelector::eOverlap_Intervals);
  782.     if ( GetStrand(ctx.GetLocation(), &ctx.GetScope()) == eNa_strand_minus ) {
  783.         sel.SetSortOrder(SAnnotSelector::eSortOrder_Reverse);  // sort in reverse biological order
  784.     } else {
  785.         sel.SetSortOrder(SAnnotSelector::eSortOrder_Normal);
  786.     }
  787.     sel.SetLimitTSE(ctx.GetHandle().GetTopLevelEntry());
  788.     sel.SetResolveTSE();
  789. }
  790. static bool s_FeatEndsOnBioseq(const CSeq_feat& feat, const CBioseq_Handle& seq)
  791. {
  792.     CSeq_loc_CI last;
  793.     for ( CSeq_loc_CI it(feat.GetLocation()); it; ++it ) {
  794.         last = it;
  795.     }
  796.     
  797.     return (last  &&  seq.IsSynonym(last.GetSeq_id()));
  798. }
  799. static CSeq_loc_Mapper* s_CreateMapper(CBioseqContext& ctx)
  800. {
  801.     if ( ctx.GetMapper() != 0 ) {
  802.         return ctx.GetMapper();
  803.     }
  804.     // do not create mapper if not segmented or segmented but not doing master style.
  805.     const CFlatFileConfig& cfg = ctx.Config();
  806.     if ( !ctx.IsSegmented()  || !(cfg.IsStyleMaster()  ||  cfg.IsFormatFTable()) ) {
  807.         return 0;
  808.     }
  809.     CSeq_loc_Mapper* mapper = new CSeq_loc_Mapper(ctx.GetHandle());
  810.     if ( mapper != 0 ) {
  811.         mapper->SetMergeAbutting();
  812.         mapper->PreserveDestinationLocs();
  813.         mapper->KeepNonmappingRanges();
  814.     }
  815.     return mapper;
  816. }
  817. static bool s_CopyCDSFromCDNA(CBioseqContext& ctx)
  818. {
  819.     return ctx.IsInGPS()  &&  !ctx.IsInNucProt()  &&  ctx.Config().CopyCDSFromCDNA();
  820. }
  821. static void s_FixLocation(CConstRef<CSeq_loc>& feat_loc, CBioseqContext& ctx)
  822. {
  823.     if ( !feat_loc->IsMix() ) {
  824.         return;
  825.     }
  826.     bool partial5 = feat_loc->IsPartialLeft();
  827.     bool partial3 = feat_loc->IsPartialRight();
  828.     CRef<CSeq_loc> loc(SeqLocMerge(ctx.GetHandle(), feat_loc->GetMix().Get(),
  829.         fFuseAbutting | fMergeIntervals));
  830.     loc->SetPartialLeft(partial5);
  831.     loc->SetPartialRight(partial3);
  832.     feat_loc.Reset(loc);
  833. }
  834. void CFlatGatherer::x_GatherFeaturesOnLocation
  835. (const CSeq_loc& loc,
  836.  SAnnotSelector& sel,
  837.  CBioseqContext& ctx) const
  838. {
  839.     CScope& scope = ctx.GetScope();
  840.     CFlatItemOStream& out = *m_ItemOS;
  841.     CRef<CSeq_loc_Mapper> mapper(s_CreateMapper(ctx));
  842.     for ( CFeat_CI it(scope, loc, sel); it; ++it ) {
  843.         const CSeq_feat& feat = it->GetOriginalFeature();
  844.         
  845.         // if part show only features ending on that part
  846.         if ( ctx.IsPart()  &&  
  847.              !s_FeatEndsOnBioseq(feat, ctx.GetHandle()) ) {
  848.             continue;
  849.         }
  850.         
  851.         CConstRef<CSeq_loc> feat_loc(&feat.GetLocation());
  852.         if ( mapper ) {
  853.             feat_loc.Reset(mapper->Map(*feat_loc));
  854.             s_FixLocation(feat_loc, ctx);
  855.         }
  856.                 
  857.         out << new CFeatureItem(feat, ctx, feat_loc);
  858.         // Add more features depending on user preferences
  859.         switch ( feat.GetData().GetSubtype() ) {
  860.         case CSeqFeatData::eSubtype_mRNA:
  861.             {{
  862.                 // optionally map CDS from cDNA onto genomic
  863.                 if ( s_CopyCDSFromCDNA(ctx)   &&  feat.IsSetProduct() ) {
  864.                     x_CopyCDSFromCDNA(feat, ctx);
  865.                 }
  866.                 break;
  867.             }}
  868.         case CSeqFeatData::eSubtype_cdregion:
  869.             {{  
  870.                 if ( !ctx.Config().IsFormatFTable() ) {
  871.                     x_GetFeatsOnCdsProduct(it->GetOriginalFeature(), ctx, mapper);
  872.                 }
  873.                 break;
  874.             }}
  875.         default:
  876.             break;
  877.         }
  878.     }
  879. }
  880. void CFlatGatherer::x_CopyCDSFromCDNA
  881. (const CSeq_feat& feat,
  882.  CBioseqContext& ctx) const
  883. {
  884.     CScope& scope = ctx.GetScope();
  885.     CBioseq_Handle cdna = scope.GetBioseqHandle(feat.GetProduct());
  886.     if ( !cdna ) {
  887.         return;
  888.     }
  889.     // NB: There is only one CDS on an mRNA
  890.     CFeat_CI cds(cdna, 0, 0, CSeqFeatData::e_Cdregion);
  891.     if ( cds ) {
  892.         // map mRNA location to the genomic
  893.         CSeq_loc_Mapper mapper(feat,
  894.                                CSeq_loc_Mapper::eProductToLocation,
  895.                                &scope);
  896.         CRef<CSeq_loc> cds_loc = mapper.Map(cds->GetLocation());
  897.         *m_ItemOS << new CFeatureItem(cds->GetOriginalFeature(), ctx, cds_loc,
  898.                                       CFeatureItem::eMapped_from_cdna);
  899.     }
  900. }
  901. void CFlatGatherer::x_GatherFeatures(void) const
  902. {
  903.     CBioseqContext& ctx = *m_Current;
  904.     const CFlatFileConfig& cfg = ctx.Config();
  905.     CScope& scope = ctx.GetScope();
  906.     CFlatItemOStream& out = *m_ItemOS;
  907.     SAnnotSelector sel;
  908.     const SAnnotSelector* selp = ctx.GetAnnotSelector();
  909.     if ( selp == 0 ) {
  910.         s_SetSelection(sel, ctx);
  911.         selp = &sel;
  912.     }
  913.     // optionally map gene from genomic onto cDNA
  914.     if ( ctx.IsInGPS()  &&  cfg.CopyGeneToCDNA()  &&
  915.          ctx.GetBiomol() == CMolInfo::eBiomol_mRNA ) {
  916.         const CSeq_feat* mrna = GetmRNAForProduct(ctx.GetHandle());
  917.         if ( mrna != 0 ) {
  918.             CConstRef<CSeq_feat> gene = 
  919.                 GetOverlappingGene(mrna->GetLocation(), scope);
  920.             if ( gene != 0 ) {
  921.                 CRef<CSeq_loc> loc(new CSeq_loc);
  922.                 loc->SetWhole(*ctx.GetPrimaryId());
  923.                 out << new CFeatureItem(*gene, ctx, loc, 
  924.                                         CFeatureItem::eMapped_from_genomic);
  925.             }
  926.         }
  927.     }
  928.     CSeq_loc loc;
  929.     if ( ctx.GetMasterLocation() != 0 ) {
  930.         loc.Assign(*ctx.GetMasterLocation());
  931.     } else {
  932.         loc.SetWhole().Assign(*ctx.GetHandle().GetSeqId());
  933.     }
  934.     // collect features
  935.     if ( ctx.IsSegmented()  &&  cfg.IsStyleMaster()  &&  cfg.OldFeatsOrder() ) {
  936.         if ( ctx.GetAnnotSelector() == 0 ) {
  937.             sel.SetResolveNone();
  938.         }
  939.         
  940.         // first do the master bioeseq
  941.         x_GatherFeaturesOnLocation(loc, sel, ctx);
  942.         // map the location on the segments        
  943.         CSeq_loc_Mapper mapper(1, ctx.GetHandle());
  944.         CRef<CSeq_loc> seg_loc(mapper.Map(loc));
  945.         if ( seg_loc ) {
  946.             // now go over each of the segments
  947.             for ( CSeq_loc_CI it(*seg_loc); it; ++it ) {
  948.                 x_GatherFeaturesOnLocation(it.GetSeq_loc(), sel, ctx);
  949.             }
  950.         }
  951.     } else {
  952.         x_GatherFeaturesOnLocation(loc, sel, ctx);
  953.     }
  954.     
  955.     if ( ctx.IsProt() ) {
  956.         // Also collect features which this protein is their product.
  957.         // Currently there are only two possible candidates: Coding regions
  958.         // and Prot features (rare).
  959.         
  960.         // look for the Cdregion feature for this protein
  961.         const CSeq_feat* cds = GetCDSForProduct(ctx.GetHandle());
  962.         if ( cds != 0 ) {
  963.             out << new CFeatureItem(*cds, ctx, &cds->GetProduct(), 
  964.                     CFeatureItem::eMapped_from_cdna);
  965.         }
  966.         // look for Prot features (only for RefSeq records or
  967.         // GenBank not release_mode).
  968.         if ( ctx.IsRefSeq()  ||  !cfg.ForGBRelease() ) {
  969.             SAnnotSelector sel(CSeqFeatData::e_Prot, true);
  970.             sel.SetLimitTSE(ctx.GetHandle().GetTopLevelEntry());
  971.             sel.SetResolveMethod(SAnnotSelector::eResolve_TSE);
  972.             sel.SetOverlapType(SAnnotSelector::eOverlap_Intervals);
  973.             for ( CFeat_CI it(ctx.GetHandle(), 0, 0, sel); it; ++it ) {  
  974.                 out << new CFeatureItem(it->GetOriginalFeature(),
  975.                                         ctx,
  976.                                         &it->GetProduct(),
  977.                                         CFeatureItem::eMapped_from_prot);
  978.             }
  979.         }
  980.     }
  981. }
  982. static bool s_IsCDD(const CSeq_feat& feat)
  983. {
  984.     ITERATE(CSeq_feat::TDbxref, it, feat.GetDbxref()) {
  985.         if ( (*it)->GetType() == CDbtag::eDbtagType_CDD ) {
  986.             return true;
  987.         }
  988.     }
  989.     return false;
  990. }
  991. void CFlatGatherer::x_GetFeatsOnCdsProduct
  992. (const CSeq_feat& feat,
  993.  CBioseqContext& ctx,
  994.  CRef<CSeq_loc_Mapper>& mapper) const
  995. {
  996.     _ASSERT(feat.GetData().IsCdregion());
  997.     const CFlatFileConfig& cfg = ctx.Config();
  998.     
  999.     if ( cfg.HideCDSProdFeatures() ) {
  1000.         return;
  1001.     }
  1002.     
  1003.     if ( !feat.CanGetProduct() ) {
  1004.         return;
  1005.     }
  1006.     CScope& scope = ctx.GetScope();
  1007.     CBioseq_Handle  prot = scope.GetBioseqHandle(feat.GetProduct());
  1008.     if ( !prot ) {
  1009.         return;
  1010.     }
  1011.         
  1012.     CFeat_CI prev;
  1013.     bool first = true;
  1014.     CSeq_loc_Mapper prot_to_nuc(feat, CSeq_loc_Mapper::eProductToLocation, &scope);
  1015.     // explore mat_peptides, sites, etc.
  1016.     for ( CFeat_CI it(prot, 0, 0); it; ++it ) {
  1017.         CSeqFeatData::ESubtype subtype = it->GetData().GetSubtype();
  1018.         if ( !(subtype == CSeqFeatData::eSubtype_region)              &&
  1019.              !(subtype == CSeqFeatData::eSubtype_site)                &&
  1020.              !(subtype == CSeqFeatData::eSubtype_bond)                &&
  1021.              !(subtype == CSeqFeatData::eSubtype_mat_peptide_aa)      &&
  1022.              !(subtype == CSeqFeatData::eSubtype_sig_peptide_aa)      &&
  1023.              !(subtype == CSeqFeatData::eSubtype_transit_peptide_aa)  &&
  1024.              !(subtype == CSeqFeatData::eSubtype_preprotein) ) {
  1025.             continue;
  1026.         }
  1027.         if ( cfg.HideCDDFeats()  &&
  1028.              subtype == CSeqFeatData::eSubtype_region  &&
  1029.              s_IsCDD(it->GetOriginalFeature()) ) {
  1030.             // passing this test prevents mapping of COG CDD region features
  1031.             continue;
  1032.         }
  1033.         // suppress duplicate features (on protein)
  1034.         if ( !first ) {
  1035.             const CSeq_loc& loc_curr = it->GetLocation();
  1036.             const CSeq_loc& loc_prev = prev->GetLocation();
  1037.             const CSeq_feat& feat_curr = it->GetOriginalFeature();
  1038.             const CSeq_feat& feat_prev = prev->GetOriginalFeature();
  1039.             if ( feat_prev.Compare(feat_curr, loc_curr, loc_prev) == 0 ) {
  1040.                 continue;
  1041.             }
  1042.         }
  1043.         // map prot location to nuc location
  1044.         CRef<CSeq_loc> loc(prot_to_nuc.Map(it->GetLocation()));
  1045.         // possibly map again (e.g. from part to master)
  1046.         if ( loc.NotEmpty()  &&  mapper.NotEmpty() ) {
  1047.             loc.Reset(mapper->Map(*loc));
  1048.         }
  1049.         if ( !loc  ||  loc->IsNull() ) {
  1050.             continue;
  1051.         }
  1052.         // make sure feature is within sublocation
  1053.         if ( ctx.GetMasterLocation() != 0 ) {
  1054.             const CSeq_loc& mloc = *ctx.GetMasterLocation();
  1055.             if ( Compare(mloc, *loc, &scope) != eContains ) {
  1056.                 continue;
  1057.             }
  1058.         }
  1059.         
  1060.         *m_ItemOS << new CFeatureItem(it->GetOriginalFeature(), ctx, 
  1061.             loc, CFeatureItem::eMapped_from_prot);
  1062.         prev = it;
  1063.         first = false;
  1064.     }    
  1065. }
  1066. END_SCOPE(objects)
  1067. END_NCBI_SCOPE
  1068. /*
  1069. * ===========================================================================
  1070. *
  1071. * $Log: gather_items.cpp,v $
  1072. * Revision 1000.2  2004/06/01 19:44:32  gouriano
  1073. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21
  1074. *
  1075. * Revision 1.21  2004/05/21 21:42:54  gorelenk
  1076. * Added PCH ncbi_pch.hpp
  1077. *
  1078. * Revision 1.20  2004/05/06 17:52:21  shomrat
  1079. * Fixed feature location
  1080. *
  1081. * Revision 1.19  2004/04/27 15:12:16  shomrat
  1082. * Added logic for partial range formatting
  1083. *
  1084. * Revision 1.18  2004/04/22 16:00:25  shomrat
  1085. * Changes in context
  1086. *
  1087. * Revision 1.17  2004/04/13 16:47:15  shomrat
  1088. * Added GBSeq format
  1089. *
  1090. * Revision 1.16  2004/04/07 14:51:24  shomrat
  1091. * Fixed typo
  1092. *
  1093. * Revision 1.15  2004/04/07 14:27:47  shomrat
  1094. * FTable format always on master bioseq
  1095. *
  1096. * Revision 1.14  2004/03/31 17:16:04  shomrat
  1097. * Set current bioseq once in calling function
  1098. *
  1099. * Revision 1.13  2004/03/30 20:31:09  shomrat
  1100. * Bug fix
  1101. *
  1102. * Revision 1.12  2004/03/26 17:24:55  shomrat
  1103. * Changes to comment gathering
  1104. *
  1105. * Revision 1.11  2004/03/25 20:39:47  shomrat
  1106. * Use handles
  1107. *
  1108. * Revision 1.10  2004/03/18 15:39:40  shomrat
  1109. * + Filtering of displayed records
  1110. *
  1111. * Revision 1.9  2004/03/12 16:57:54  shomrat
  1112. * Filter viewable bioseqs; Use new location mapping
  1113. *
  1114. * Revision 1.8  2004/03/10 16:22:44  shomrat
  1115. * Use reference to object
  1116. *
  1117. * Revision 1.7  2004/03/05 18:45:19  shomrat
  1118. * changes to feature gathering
  1119. *
  1120. * Revision 1.6  2004/02/19 18:11:25  shomrat
  1121. * Set feature iterator selector based on user flags
  1122. *
  1123. * Revision 1.5  2004/02/11 22:52:41  shomrat
  1124. * using types in flag file
  1125. *
  1126. * Revision 1.4  2004/02/11 16:52:12  shomrat
  1127. * completed implementation of featture gathering
  1128. *
  1129. * Revision 1.3  2004/01/14 16:15:03  shomrat
  1130. * minor changes to accomodate for GFF format
  1131. *
  1132. * Revision 1.2  2003/12/18 17:43:34  shomrat
  1133. * context.hpp moved
  1134. *
  1135. * Revision 1.1  2003/12/17 20:21:48  shomrat
  1136. * Initial Revision (adapted from flat lib)
  1137. *
  1138. *
  1139. * ===========================================================================
  1140. */