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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: gff_formatter.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:44:46  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: gff_formatter.cpp,v 1000.1 2004/06/01 19:44:46 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
  36. *
  37. * File Description:
  38. *           
  39. *
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <objects/seqfeat/Genetic_code_table.hpp>
  44. #include <objects/general/Date.hpp>
  45. #include <objects/seq/Bioseq.hpp>
  46. #include <objmgr/util/sequence.hpp>
  47. #include <objmgr/util/feature.hpp>
  48. #include <objmgr/seq_vector.hpp>
  49. #include <objtools/format/gff_formatter.hpp>
  50. #include <objtools/format/items/locus_item.hpp>
  51. #include <objtools/format/items/date_item.hpp>
  52. #include <objtools/format/items/feature_item.hpp>
  53. #include <objtools/format/items/basecount_item.hpp>
  54. #include <objtools/format/items/sequence_item.hpp>
  55. #include <objtools/format/items/ctrl_items.hpp>
  56. #include <objtools/format/context.hpp>
  57. #include <algorithm>
  58. BEGIN_NCBI_SCOPE
  59. BEGIN_SCOPE(objects)
  60. CGFFFormatter::CGFFFormatter(void) :
  61.     m_GFFFlags(CGFFFormatter::fGTFCompat)
  62. {
  63. }
  64. void CGFFFormatter::Start(IFlatTextOStream& text_os)
  65. {
  66.     list<string> l;
  67.     l.push_back("##gff-version 2");
  68.     l.push_back("##source-version NCBI C++ formatter 0.1");
  69.     l.push_back("##date " + CurrentTime().AsString("Y-M-D"));
  70.     text_os.AddParagraph(l);
  71. }
  72. void CGFFFormatter::StartSection(const CStartSectionItem& ssec, IFlatTextOStream& text_os)
  73. {
  74.     list<string> l;
  75.     CBioseqContext& bctx = *ssec.GetContext();
  76.     switch (bctx.GetMol()) {
  77.     case CSeq_inst::eMol_dna:  m_SeqType = "DNA";      break;
  78.     case CSeq_inst::eMol_rna:  m_SeqType = "RNA";      break;
  79.     case CSeq_inst::eMol_aa:   m_SeqType = "Protein";  break;
  80.     default:                   m_SeqType.erase();      break;
  81.     }
  82.     if ( !m_SeqType.empty() ) {
  83.         l.push_back("##Type " + m_SeqType + ' '
  84.                     + bctx.GetAccession());
  85.     }
  86.     text_os.AddParagraph(l);
  87. }
  88. void CGFFFormatter::EndSection(const CEndSectionItem&, IFlatTextOStream& text_os)
  89. {
  90.     if ( !m_EndSequence.empty() ) {
  91.         list<string> l;
  92.         l.push_back(m_EndSequence);
  93.         text_os.AddParagraph(l);
  94.     }
  95. }
  96. void CGFFFormatter::FormatLocus
  97. (const CLocusItem& locus, 
  98.  IFlatTextOStream& text_os)
  99. {
  100.     m_Strandedness = locus.GetStrand();
  101. }
  102. void CGFFFormatter::FormatDate
  103. (const CDateItem& date,
  104.  IFlatTextOStream& text_os)
  105. {
  106.     m_Date.erase();
  107.     const CDate* d = date.GetUpdateDate();
  108.     if ( d != 0 ) {
  109.         d->GetDate(&m_Date, "%4Y-%{%2M%|??%}-%{%2D%|??%}");
  110.     }
  111. }
  112. ///////////////////////////////////////////////////////////////////////////
  113. //
  114. // FEATURES
  115. void CGFFFormatter::FormatFeature
  116. (const CFeatureItemBase& f,
  117.  IFlatTextOStream& text_os)
  118. {
  119.     const CSeq_feat& seqfeat = f.GetFeat();
  120.     string           key(f.GetKey()), oldkey;
  121.     bool             gtf     = false;
  122.     CBioseqContext& ctx = *f.GetContext();
  123.     CScope* scope = &ctx.GetScope();
  124.     // CSeq_loc         tentative_stop;
  125.     if ((m_GFFFlags & fGTFCompat)  &&  !ctx.IsProt()
  126.         &&  (key == "CDS"  ||  key == "exon")) {
  127.         gtf = true;
  128.     } else if ((m_GFFFlags & fGTFCompat)
  129.                &&  ctx.GetMol() == CSeq_inst::eMol_dna
  130.                &&  seqfeat.GetData().IsRna()) {
  131.         oldkey = key;
  132.         key    = "exon";
  133.         gtf    = true;
  134.     } else if ((m_GFFFlags & fGTFOnly) == fGTFOnly) {
  135.         return;
  136.     }
  137.     CConstRef<CFlatFeature> feat = f.Format();
  138.     list<string>  l;
  139.     list<string>  attr_list;
  140.     if ( !oldkey.empty() ) {
  141.         attr_list.push_back("gbkey "" + oldkey + "";");
  142.     }
  143.     ITERATE (CFlatFeature::TQuals, it, feat->GetQuals()) {
  144.         string name = (*it)->GetName();
  145.         if (name == "codon_start"  ||  name == "translation"
  146.             ||  name == "transcription") {
  147.             continue; // suppressed to reduce verbosity
  148.         } else if (name == "number"  &&  key == "exon") {
  149.             name = "exon_number";
  150.         } else if ((m_GFFFlags & fGTFCompat)  &&  !ctx.IsProt()
  151.                    &&  name == "gene") {
  152.             string gene_id = x_GetGeneID(*feat, (*it)->GetValue(), ctx);
  153.             if (key != "gene") {
  154.                 string transcript_id = x_GetTranscriptID(*feat, gene_id, ctx);
  155.                 attr_list.push_front
  156.                     ("transcript_id "" + transcript_id + "";");
  157.             }
  158.             attr_list.push_front("gene_id "" + gene_id + "";");
  159.             continue;
  160.         }
  161.         string value;
  162.         NStr::Replace((*it)->GetValue(), " b", kEmptyStr, value);
  163.         string value2(NStr::PrintableString(value));
  164.         // some parsers may be dumb, so quote further
  165.         value.erase();
  166.         ITERATE (string, c, value2) {
  167.             switch (*c) {
  168.             case ' ':  value += "\x20"; break;
  169.             case '"': value += "x22";   break; // already backslashed
  170.             case '#':  value += "\x23"; break;
  171.             default:   value += *c;
  172.             }
  173.         }
  174.         attr_list.push_back(name + " "" + value + "";");
  175.     }
  176.     string attrs(NStr::Join(attr_list, " "));
  177.     string source = x_GetSourceName(ctx);
  178.     int frame = -1;
  179.     if (seqfeat.GetData().IsCdregion()  &&  !ctx.IsProt() ) {
  180.         const CCdregion& cds = seqfeat.GetData().GetCdregion();
  181.         frame = max(cds.GetFrame() - 1, 0);
  182.     }
  183.     CRef<CSeq_loc> tentative_stop;
  184.     if (gtf  &&  seqfeat.GetData().IsCdregion()) {
  185.         const CCdregion& cds = seqfeat.GetData().GetCdregion();
  186.         if ( !f.GetLoc().IsPartialRight()  &&  seqfeat.IsSetProduct() ) {
  187.             TSeqPos loc_len = sequence::GetLength(f.GetLoc(), scope);
  188.             TSeqPos prod_len = sequence::GetLength(seqfeat.GetProduct(),
  189.                                                    scope);
  190.             if (loc_len >= frame + 3 * prod_len + 3) {
  191.                 SRelLoc::TRange range;
  192.                 range.SetFrom(frame + 3 * prod_len);
  193.                 range.SetTo  (frame + 3 * prod_len + 2);
  194.                 // needs to be partial for TranslateCdregion to DTRT
  195.                 range.SetFuzz_from().SetLim(CInt_fuzz::eLim_lt);
  196.                 SRelLoc::TRanges ranges;
  197.                 ranges.push_back(CRef<SRelLoc::TRange>(&range));
  198.                 tentative_stop = SRelLoc(f.GetLoc(), ranges).Resolve(scope);
  199.             }
  200.             if (tentative_stop.NotEmpty()  &&  !tentative_stop->IsNull()) {
  201.                 string s;
  202.                 CCdregion_translate::TranslateCdregion
  203.                     (s, ctx.GetHandle(), *tentative_stop, cds);
  204.                 if (s != "*") {
  205.                     tentative_stop.Reset();
  206.                 }
  207.             } else {
  208.                 tentative_stop.Reset();
  209.             }
  210.         }
  211.     }
  212.     x_AddFeature(l, f.GetLoc(), source, key, "." /*score*/, frame, attrs, gtf, ctx, tentative_stop);
  213.     if (gtf  &&  seqfeat.GetData().IsCdregion()) {
  214.         const CCdregion& cds = seqfeat.GetData().GetCdregion();
  215.         if ( !f.GetLoc().IsPartialLeft() ) {
  216.             CRef<CSeq_loc> tentative_start;
  217.             {{
  218.                 CRef<SRelLoc::TRange> range(new SRelLoc::TRange);
  219.                 SRelLoc::TRanges      ranges;
  220.                 range->SetFrom(frame);
  221.                 range->SetTo(frame + 2);
  222.                 ranges.push_back(range);
  223.                 tentative_start = SRelLoc(f.GetLoc(), ranges).Resolve(scope);
  224.             }}
  225.             string s;
  226.             ctx.GetHandle().GetSequenceView
  227.                 (*tentative_start, CBioseq_Handle::eViewConstructed)
  228.                 .GetSeqData(0, 3, s);
  229.             const CTrans_table* tt;
  230.             if (cds.IsSetCode()) {
  231.                 tt = &CGen_code_table::GetTransTable(cds.GetCode());
  232.             } else {
  233.                 tt = &CGen_code_table::GetTransTable(1);
  234.             }
  235.             if (s.size() == 3
  236.                 &&  tt->IsAnyStart(tt->SetCodonState(s[0], s[1], s[2]))) {
  237.                 x_AddFeature(l, *tentative_start, source, "start_codon",
  238.                              "." /* score */, 0, attrs, gtf, ctx);
  239.             }
  240.         }
  241.         if ( tentative_stop ) {
  242.             x_AddFeature(l, *tentative_stop, source, "stop_codon",
  243.                                  "." /* score */, 0, attrs, gtf, ctx);
  244.         }
  245.     }
  246.     text_os.AddParagraph(l, &seqfeat);
  247. }
  248. ///////////////////////////////////////////////////////////////////////////
  249. //
  250. // BASE COUNT
  251. // used as a trigger for the sequence header
  252. void CGFFFormatter::FormatBasecount
  253. (const CBaseCountItem& bc,
  254.  IFlatTextOStream& text_os)
  255. {
  256.     if ( !(m_GFFFlags & fShowSeq) )
  257.         return;
  258.     CBioseqContext& ctx = *bc.GetContext();
  259.     list<string> l;
  260.     l.push_back("##" + m_SeqType + ' ' + ctx.GetAccession());
  261.     text_os.AddParagraph(l);
  262.     m_EndSequence = "##end-" + m_SeqType;
  263. }
  264. ///////////////////////////////////////////////////////////////////////////
  265. //
  266. // SEQUENCE
  267. void CGFFFormatter::FormatSequence
  268. (const CSequenceItem& seq,
  269.  IFlatTextOStream& text_os)
  270. {
  271.     if ( !(m_GFFFlags & fShowSeq) )
  272.         return;
  273.     CBioseqContext& ctx = *seq.GetContext();
  274.     list<string> l;
  275.     CSeqVector v = seq.GetSequence();
  276.     v.SetCoding(CBioseq_Handle::eCoding_Iupac);
  277.     CSeqVector_CI vi(v);
  278.     string s;
  279.     while (vi) {
  280.         s.erase();
  281.         vi.GetSeqData(s, 70);
  282.         l.push_back("##" + s);
  283.     }
  284.     text_os.AddParagraph(l, ctx.GetHandle().GetCompleteBioseq());
  285. }
  286. // Private
  287. string CGFFFormatter::x_GetGeneID
  288. (const CFlatFeature& feat,
  289.  const string& gene,
  290.  CBioseqContext& ctx) const
  291. {
  292.     const CSeq_feat& seqfeat = feat.GetFeat();
  293.     string               main_acc;
  294.     if (ctx.IsPart()) {
  295.         const CSeq_id& id = *(ctx.GetMaster().GetHandle().GetSeqId());
  296.         main_acc = ctx.GetPreferredSynonym(id).GetSeqIdString(true);
  297.     } else {
  298.         main_acc = ctx.GetAccession();
  299.     }
  300.     string               gene_id   = main_acc + ':' + gene;
  301.     CConstRef<CSeq_feat> gene_feat = sequence::GetBestOverlappingFeat
  302.         (seqfeat.GetLocation(), CSeqFeatData::e_Gene,
  303.          sequence::eOverlap_Interval, ctx.GetScope());
  304.     return gene_id;
  305. }
  306. string CGFFFormatter::x_GetTranscriptID
  307. (const CFlatFeature& feat,
  308.  const string& gene_id,
  309.  CBioseqContext& ctx) const
  310. {
  311.     const CSeq_feat& seqfeat = feat.GetFeat();
  312.     // if our feature already is an mRNA, we need look no further
  313.     CConstRef<CSeq_feat> mrna_feat;
  314.     if (seqfeat.GetData().GetSubtype() == CSeqFeatData::eSubtype_mRNA) {
  315.         mrna_feat.Reset(&seqfeat);
  316.     } else {
  317.         // search for a best overlapping mRNA
  318.         // we start with a scan through the product accessions because we need
  319.         // to insure that the chosen transcript does indeed match what we want
  320.         if (seqfeat.IsSetProduct()) {
  321.             try {
  322.                 // this may throw, if the product spans multiple sequences
  323.                 // this would be extremely unlikely, but we catch anyway
  324.                 const CSeq_id& product_id =
  325.                     sequence::GetId(seqfeat.GetProduct());
  326.                 SAnnotSelector sel;
  327.                 sel.SetOverlapIntervals()
  328.                     .ExcludeNamedAnnots("SNP")
  329.                     .SetResolveAll()
  330.                     .SetFeatSubtype(CSeqFeatData::eSubtype_mRNA);
  331.                 CFeat_CI feat_iter(ctx.GetScope(), seqfeat.GetLocation(), sel);
  332.                 for ( ;  feat_iter  &&  !mrna_feat;  ++feat_iter) {
  333.                     // we grab the mRNA product, if available, and scan it for
  334.                     // a CDS feature.  the CDS feature should point to the same
  335.                     // product as our current feature.
  336.                     const CSeq_feat& mrna = feat_iter->GetOriginalFeature();
  337.                     if ( !mrna.IsSetProduct() ) {
  338.                         continue;
  339.                     }
  340.                     // make sure the feature contains our feature of interest
  341.                     sequence::ECompare comp =
  342.                         sequence::Compare(mrna.GetLocation(),
  343.                                           seqfeat.GetLocation());
  344.                     if (comp != sequence::eContains  &&
  345.                         comp != sequence::eSame) {
  346.                         continue;
  347.                     }
  348.                     CBioseq_Handle handle =
  349.                         ctx.GetScope().GetBioseqHandle(mrna.GetProduct());
  350.                     if ( !handle ) {
  351.                         continue;
  352.                     }
  353.                     SAnnotSelector cds_sel(sel);
  354.                     cds_sel.SetFeatSubtype(CSeqFeatData::eSubtype_cdregion);
  355.                     CFeat_CI other_iter(ctx.GetScope(),
  356.                                         mrna.GetProduct(),
  357.                                         cds_sel);
  358.                     for ( ;  other_iter  &&  !mrna_feat;  ++other_iter) {
  359.                         const CSeq_feat& cds = other_iter->GetOriginalFeature();
  360.                         if ( !cds.IsSetProduct() ) {
  361.                             continue;
  362.                         }
  363.                         CBioseq_Handle prot_handle =
  364.                             ctx.GetScope().GetBioseqHandle(cds.GetProduct());
  365.                         if ( !prot_handle ) {
  366.                             continue;
  367.                         }
  368.                         if (prot_handle.IsSynonym(product_id)) {
  369.                             // got it!
  370.                             mrna_feat.Reset(&mrna);
  371.                             break;
  372.                         }
  373.                     }
  374.                 }
  375.             }
  376.             catch (...) {
  377.             }
  378.         }
  379.         //
  380.         // try to find the best by overlaps alone
  381.         //
  382.         if ( !mrna_feat ) {
  383.             mrna_feat = sequence::GetBestOverlappingFeat
  384.                 (seqfeat.GetLocation(), CSeqFeatData::eSubtype_mRNA,
  385.                  sequence::eOverlap_CheckIntervals, ctx.GetScope());
  386.         }
  387.     }
  388.     //
  389.     // check if the mRNA feature we found has a product
  390.     //
  391.     if (mrna_feat.GetPointer()  &&  mrna_feat->IsSetProduct()) {
  392.         try {
  393.             const CSeq_id& id = sequence::GetId(mrna_feat->GetProduct());
  394.             string transcript_id =
  395.                 ctx.GetPreferredSynonym(id).GetSeqIdString(true);
  396.             return transcript_id;
  397.         }
  398.         catch (...) {
  399.         }
  400.     }
  401.     //
  402.     // nothing found, so fake it
  403.     //
  404.     // failed to get transcript id, so we fake a globally unique one based
  405.     // on the gene id
  406.     m_Transcripts[gene_id].push_back(CConstRef<CSeq_feat>(&seqfeat));
  407.     string transcript_id = gene_id;
  408.     transcript_id += ":unknown_transcript_";
  409.     transcript_id += NStr::IntToString(m_Transcripts[gene_id].size());
  410.     return transcript_id;
  411. }
  412. string CGFFFormatter::x_GetSourceName(CBioseqContext& ctx) const
  413. {
  414.     // XXX - get from annot name (not presently available from IFF)?
  415.     switch ( ctx.GetPrimaryId()->Which() ) {
  416.     case CSeq_id::e_Local:                           return "Local";
  417.     case CSeq_id::e_Gibbsq: case CSeq_id::e_Gibbmt:
  418.     case CSeq_id::e_Giim:   case CSeq_id::e_Gi:      return "GenInfo";
  419.     case CSeq_id::e_Genbank:                         return "Genbank";
  420.     case CSeq_id::e_Swissprot:                       return "SwissProt";
  421.     case CSeq_id::e_Patent:                          return "Patent";
  422.     case CSeq_id::e_Other:                           return "RefSeq";
  423.     case CSeq_id::e_General:
  424.         return ctx.GetPrimaryId()->GetGeneral().GetDb();
  425.     default:
  426.     {
  427.         string source
  428.             (CSeq_id::SelectionName(ctx.GetPrimaryId()->Which()));
  429.         return NStr::ToUpper(source);
  430.     }
  431.     }
  432. }
  433. void CGFFFormatter::x_AddFeature
  434. (list<string>& l,
  435.  const CSeq_loc& loc,
  436.  const string& source,
  437.  const string& key,
  438.  const string& score,
  439.  int frame,
  440.  const string& attrs,
  441.  bool gtf,
  442.  CBioseqContext& ctx,
  443.  bool tentative_stop) const
  444. {
  445.     
  446.     int num_exons = 0;
  447.     for (CSeq_loc_CI it(loc);  it;  ++it) {
  448.         ++num_exons;
  449.     }
  450.     int exon_number = 1;
  451.     for (CSeq_loc_CI it(loc);  it;  ++it) {
  452.         TSeqPos from   = it.GetRange().GetFrom(), to = it.GetRange().GetTo();
  453.         char    strand = '+';
  454.         if (IsReverse(it.GetStrand())) {
  455.             strand = '-';
  456.         } else if (it.GetRange().IsWhole()
  457.                    ||  (m_Strandedness <= CSeq_inst::eStrand_ss
  458.                         &&  ctx.GetMol() != CSeq_inst::eMol_dna)) {
  459.             strand = '.'; // N/A
  460.         }
  461.         if (it.GetRange().IsWhole()) {
  462.             to = sequence::GetLength(it.GetSeq_id(), &ctx.GetScope()) - 1;
  463.         }
  464.         if ( tentative_stop  &&  (exon_number == num_exons) ) {
  465.             to -= 3;
  466.         }
  467.         string extra_attrs;
  468.         if (gtf  &&  attrs.find("exon_number ") == NPOS) {
  469.             CSeq_loc       loc2;
  470.             CSeq_interval& si = loc2.SetInt();
  471.             si.SetFrom(from);
  472.             si.SetTo(to);
  473.             si.SetStrand(it.GetStrand());
  474.             si.SetId(const_cast<CSeq_id&>(it.GetSeq_id()));
  475.             CConstRef<CSeq_feat> exon = sequence::GetBestOverlappingFeat
  476.                 (loc2, CSeqFeatData::eSubtype_exon,
  477.                  sequence::eOverlap_Contains, ctx.GetScope());
  478.             if (exon.NotEmpty()  &&  exon->IsSetQual()) {
  479.                 ITERATE (CSeq_feat::TQual, q, exon->GetQual()) {
  480.                     if ( !NStr::CompareNocase((*q)->GetQual(), "number") ) {
  481.                         int n = NStr::StringToNumeric((*q)->GetVal());
  482.                         if (n >= exon_number) {
  483.                             exon_number = n;
  484.                             break;
  485.                         }
  486.                     }
  487.                 }
  488.             }
  489.             extra_attrs = " exon_number "" + NStr::IntToString(exon_number)
  490.                 + "";";
  491.             ++exon_number;
  492.         }
  493.         if ( sequence::IsSameBioseq(it.GetSeq_id(), *ctx.GetPrimaryId(),
  494.                                     &ctx.GetScope()) ) {
  495.             // conditionalize printing, but update state regardless
  496.             l.push_back(ctx.GetAccession() + 't'
  497.                         + source + 't'
  498.                         + key + 't'
  499.                         + NStr::UIntToString(from + 1) + 't'
  500.                         + NStr::UIntToString(to + 1) + 't'
  501.                         + score + 't'
  502.                         + strand + 't'
  503.                         + (frame >= 0 ? char(frame + '0') : '.') + "t"
  504.                         + attrs + extra_attrs);
  505.         }
  506.         if (frame >= 0) {
  507.             frame = (frame + to - from + 1) % 3;
  508.         }
  509.     }
  510. }
  511. END_SCOPE(objects)
  512. END_NCBI_SCOPE
  513. /*
  514. * ===========================================================================
  515. *
  516. * $Log: gff_formatter.cpp,v $
  517. * Revision 1000.1  2004/06/01 19:44:46  gouriano
  518. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  519. *
  520. * Revision 1.7  2004/05/21 21:42:54  gorelenk
  521. * Added PCH ncbi_pch.hpp
  522. *
  523. * Revision 1.6  2004/05/08 12:12:33  dicuccio
  524. * Altered handling of transcript_id - make transcript_id globally unique and
  525. * trackable across CDS features as well as mRNA features
  526. *
  527. * Revision 1.5  2004/05/06 17:54:29  shomrat
  528. * Use CConstRef instead of reference
  529. *
  530. * Revision 1.4  2004/04/22 16:02:12  shomrat
  531. * fixed stop_codon
  532. *
  533. * Revision 1.3  2004/03/25 20:42:41  shomrat
  534. * Master returns a CBioseq_Handle instead of a CBioseq
  535. *
  536. * Revision 1.2  2004/02/11 16:59:11  shomrat
  537. * removed unused variable
  538. *
  539. * Revision 1.1  2004/01/14 16:07:29  shomrat
  540. * Initial Revision
  541. *
  542. *
  543. * ===========================================================================
  544. */