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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: parse.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:08:37  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: parse.cpp,v 1000.2 2004/06/01 18:08:37 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.  * Authors:  Alexandre Souvorov
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include "gene_finder.hpp"
  41. BEGIN_NCBI_SCOPE
  42. template<class T> inline void PushState(ParseVec<T>* vecp, int strand, int point)
  43. {
  44.     for (int phase = 0;  phase < 3;  ++phase) {
  45.         vecp[phase].push_back(T(strand,phase,point));
  46.         ++vecp[phase].num;
  47.     }
  48. }
  49. template<class T> inline void PushState(ParseVec<T>& vec, int strand, int point)
  50. {
  51.     vec.push_back(T(strand,point));
  52.     ++vec.num;
  53. }
  54. inline void PushState(ParseVec<LastExon>& vec, int strand, int point)
  55. {
  56.     vec.push_back(LastExon(strand,2,point));
  57.     ++vec.num;
  58. }
  59. inline void PushState(ParseVec<FirstExon>& vec, int strand, int point)
  60. {
  61.     vec.push_back(FirstExon(strand,0,point));
  62.     ++vec.num;
  63. }
  64. template<class L, class R> inline 
  65. bool TooFar(const L& left, const R& right, double score) 
  66.     if (left.MScore() == BadScore) {
  67.         return true;
  68.     }
  69.     int len = right.Stop() - left.Stop();
  70.     return (len > TooFarLen  &&  score + left.MScore() < right.Score());
  71. }
  72. struct RState
  73. {
  74.     RState(const HMM_State& l, const HMM_State& r)
  75.     {
  76.         lsp = r.LeftState();
  77.         rsp = const_cast<HMM_State*>(&r);
  78.         rsp->UpdateLeftState(l);
  79.     }
  80.     ~RState() { rsp->UpdateLeftState(*lsp); } 
  81.     const HMM_State* lsp;
  82.     HMM_State* rsp;
  83. };
  84. template<class Left, class Right> inline
  85. bool EvaluateNewScore(const Left& left, const Right& right, double& rscore, 
  86.                       bool& openrgn, bool& inalign)
  87. {
  88.     rscore = BadScore;
  89.     RState rst(left,right);
  90.     int len = right.Stop() - left.Stop();
  91.     if (len > right.MaxLen()) {
  92.         return false;
  93.     }
  94.     if ( !right.NoRightEnd()  &&  len < right.MinLen() ) {
  95.         return true;
  96.     }
  97.     double scr, score = 0;
  98.     if (left.isPlus()) {
  99.         scr = left.BranchScore(right);
  100.         if (scr == BadScore) {
  101.             return true;
  102.         }
  103.     } else {
  104.         scr = right.BranchScore(left);
  105.         if (scr == BadScore) {
  106.             return true;
  107.         }
  108.         scr += right.DenScore() - left.DenScore();
  109.     }
  110.     score += scr;
  111.     // this check is frame - dependent and MUST be after BranchScore
  112.     if (right.StopInside()) {
  113.         return false;
  114.     }     
  115.     if (right.NoRightEnd()) {
  116.         scr = right.ClosingLengthScore();
  117.     } else {
  118.         scr = right.LengthScore();
  119.     }
  120.     if (scr == BadScore) {
  121.         return true;
  122.     }
  123.     score += scr;
  124.     scr = right.RgnScore();
  125.     if (scr == BadScore) {
  126.         return true;
  127.     }
  128.     score += scr;
  129.     if ( !right.NoRightEnd() ) {
  130.         scr = right.TermScore();
  131.         if (scr == BadScore) {
  132.             return true;
  133.         }
  134.         score += scr;
  135.     }
  136.     openrgn = right.OpenRgn();
  137.     inalign = right.InAlignment();
  138.     rscore = score;
  139.     return true;
  140. }
  141. class RightIsExon {};
  142. class RightIsNotExon {};
  143. template<class L, class R> // template for all right exons
  144. inline bool ForwardStep(const L& left, R& right, RightIsExon rie)
  145. {
  146.     double score;
  147.     bool openrgn, inalign;
  148.     if ( !EvaluateNewScore(left,right,score,openrgn,inalign) ) {
  149.         return false;
  150.     } else if (score == BadScore) {
  151.         return true;
  152.     }
  153.     if (left.Score() != BadScore  &&  openrgn  &&  !inalign) {
  154.         double scr = score + left.Score();
  155.         if (scr > right.Score()) {
  156.             right.UpdateLeftState(left);
  157.             right.UpdateScore(scr);
  158.         }
  159.     }
  160.     if ( !openrgn ) {
  161.         return false;
  162.     }
  163.     return true;
  164. }
  165. template<class L, class R> // template for all right non - exons
  166. inline bool ForwardStep(const L& left, R& right, RightIsNotExon rine)
  167. {
  168.     double score;
  169.     bool openrgn, inalign;
  170.     if ( !EvaluateNewScore(left,right,score,openrgn,inalign) ) {
  171.         return false;
  172.     } else if (score == BadScore) {
  173.         return true;
  174.     }
  175.     if (left.Score() != BadScore  &&  openrgn  &&  !inalign) {
  176.         double scr = score + left.Score();
  177.         if (scr > right.Score()) {
  178.             right.UpdateLeftState(left);
  179.             right.UpdateScore(scr);
  180.         }
  181.     }
  182.     if ( !openrgn  ||  TooFar(left, right, score) ) {
  183.         return false;
  184.     }
  185.     return true;
  186. }
  187. template<class L, class R> // template for all right exons
  188. inline void MakeStep(ParseVec<L>& lvec, ParseVec<R>& rvec, RightIsExon rie)
  189. {
  190.     if (lvec.num < 0) {
  191.         return;
  192.     }
  193.     int i = lvec.num;
  194.     if (lvec[i].Stop() == rvec[rvec.num].Stop()) {
  195.         --i;
  196.     }
  197.     while (i >= 0  &&  ForwardStep(lvec[i--],rvec[rvec.num],rie)) {
  198.     }
  199.     if (rvec.num > 0) {
  200.         rvec[rvec.num].UpdatePrevExon(rvec[rvec.num - 1]);
  201.     }
  202. }
  203. template<class L, class R> // template for all right non - exons
  204. inline void MakeStep(ParseVec<L>& lvec, ParseVec<R>& rvec, RightIsNotExon rine)
  205. {
  206.     if (lvec.num < 0) {
  207.         return;
  208.     }
  209.     R& right = rvec[rvec.num];
  210.     int i = lvec.num;
  211.     int rlimit = right.Stop();
  212.     if (lvec[i].Stop() == rlimit) {
  213.         --i;
  214.     }
  215.     int nearlimit = max(0,rlimit - TooFarLen);
  216.     while (i >= 0  &&  lvec[i].Stop() >= nearlimit) {
  217.         if ( !ForwardStep(lvec[i--],right,rine) ) {
  218.             return;
  219.         }
  220.     }
  221.     if (i < 0) {
  222.         return;
  223.     }
  224.     for (const L* p = &lvec[i];  p !=0;  p = p->PrevExon()) {
  225.         if ( !ForwardStep(*p,right,rine) ) {
  226.             return;
  227.         }
  228.     }
  229. }
  230. // R / L indicates that left / right parameter is a 3 - element array
  231. template<class L, class R, class D> 
  232. inline void MakeStepR(L& lvec, R rvec, D d)
  233. {
  234.     for (int phr = 0;  phr < 3;  ++phr) {
  235.         MakeStep(lvec, rvec[phr], d);
  236.     }
  237. }
  238. template<class L, class R, class D> 
  239. inline void MakeStepL(L lvec, R& rvec, D d)
  240. {
  241.     for (int phl = 0;  phl < 3;  ++phl) {
  242.         MakeStep(lvec[phl], rvec, d);
  243.     }
  244. }
  245. template<class L, class R, class D> 
  246. inline void MakeStepLR(L lvec, R rvec, D d)
  247. {
  248.     for (int phl = 0;  phl < 3;  ++phl) {
  249.         for (int phr = 0;  phr < 3;  ++phr)
  250.         {
  251.             MakeStep(lvec[phl], rvec[phr], d);
  252.         }
  253.     }
  254. }
  255. template<class L, class R, class D> 
  256. inline void MakeStepLR(L lvec, R rvec, D d, int shift)
  257. {
  258.     for (int phl = 0;  phl < 3;  ++phl) {
  259.         int phr = (shift + phl)%3;
  260.         MakeStep(lvec[phl], rvec[phr], d);
  261.     }
  262. }
  263. Parse::Parse(const SeqScores& ss) : seqscr(ss)
  264. {
  265.     try {
  266.         igplus.reserve (seqscr.StartNumber(Plus) + 1);
  267.         igminus.reserve(seqscr.StopNumber (Minus) + 1);
  268.         feminus.reserve(seqscr.StartNumber(Minus) + 1);
  269.         leplus.reserve (seqscr.StopNumber (Plus) + 1);
  270.         seplus.reserve (seqscr.StopNumber (Plus) + 1);
  271.         seminus.reserve(seqscr.StartNumber(Minus) + 1);
  272.         for (int phase = 0;  phase < 3;  ++phase) {
  273.             inplus[phase ].reserve(seqscr.AcceptorNumber(Plus) + 1);
  274.             inminus[phase].reserve(seqscr.DonorNumber   (Minus) + 1);
  275.             feplus[phase ].reserve(seqscr.DonorNumber   (Plus) + 1);
  276.             ieplus[phase ].reserve(seqscr.DonorNumber   (Plus) + 1);
  277.             ieminus[phase].reserve(seqscr.AcceptorNumber(Minus) + 1);
  278.             leminus[phase].reserve(seqscr.AcceptorNumber(Minus) + 1);
  279.         }
  280.     }
  281.     catch(bad_alloc&) {
  282.         NCBI_THROW(CGnomonException, eGenericError,
  283.                    "Not enough memory in Parse");
  284.     }
  285.     int len = seqscr.SeqLen();
  286.     RightIsExon rie;
  287.     RightIsNotExon rine;
  288.     for (int i = 0;  i < len;  ++i) {
  289.         if (seqscr.AcceptorScore(i,Plus) != BadScore) {
  290.             PushState (inplus,Plus,i);
  291.             MakeStepLR(ieplus,inplus,rine,1);
  292.             MakeStepLR(feplus,inplus,rine,1);
  293.         }
  294.         if (seqscr.AcceptorScore(i,Minus) != BadScore) {
  295.             PushState (ieminus,Minus,i);
  296.             PushState (leminus,Minus,i);
  297.             MakeStepLR(inminus,ieminus,rie);
  298.             MakeStepR(igminus,leminus,rie);
  299.         }
  300.         if (seqscr.DonorScore(i,Plus) != BadScore) {
  301.             PushState (feplus,Plus,i);
  302.             PushState (ieplus,Plus,i);
  303.             MakeStepLR(inplus,ieplus,rie);
  304.             MakeStepR(igplus,feplus,rie);
  305.         }
  306.         if (seqscr.DonorScore(i,Minus) != BadScore) {
  307.             PushState (inminus,Minus,i);
  308.             MakeStepLR(leminus,inminus,rine,0);
  309.             MakeStepLR(ieminus,inminus,rine,0);
  310.         }
  311.         if (seqscr.StartScore(i,Plus) != BadScore) {
  312.             PushState(igplus,Plus,i);
  313.             MakeStep (seplus,igplus,rine);
  314.             MakeStep (seminus,igplus,rine);
  315.             MakeStep (leplus,igplus,rine);
  316.             MakeStep (feminus,igplus,rine);
  317.         }
  318.         if (seqscr.StartScore(i,Minus) != BadScore) {
  319.             PushState(feminus,Minus,i);
  320.             PushState(seminus,Minus,i);
  321.             MakeStepL(inminus,feminus,rie);
  322.             MakeStep (igminus,seminus,rie);
  323.         }
  324.         if (seqscr.StopScore(i,Plus) != BadScore) {
  325.             PushState(leplus,Plus,i);
  326.             PushState(seplus,Plus,i);
  327.             MakeStepL(inplus,leplus,rie);
  328.             MakeStep (igplus,seplus,rie);
  329.         }
  330.         if (seqscr.StopScore(i,Minus) != BadScore) {
  331.             PushState(igminus,Minus,i);
  332.             MakeStep (seplus,igminus,rine);
  333.             MakeStep (seminus,igminus,rine);
  334.             MakeStep (leplus,igminus,rine);
  335.             MakeStep (feminus,igminus,rine);
  336.         }
  337.     }
  338.     PushState (inplus,Plus,-1);
  339.     MakeStepLR(ieplus,inplus,rine,1);
  340.     MakeStepLR(feplus,inplus,rine,1);
  341.     PushState (ieminus,Minus,-1);
  342.     MakeStepLR(inminus,ieminus,rie);
  343.     PushState(leminus,Minus,-1);
  344.     MakeStepR(igminus,leminus,rie);
  345.     PushState (ieplus,Plus,-1);
  346.     MakeStepLR(inplus,ieplus,rie);
  347.     PushState(feplus,Plus,-1);
  348.     MakeStepR(igplus,feplus,rie);
  349.     PushState (inminus,Minus,-1);
  350.     MakeStepLR(leminus,inminus,rine,0);
  351.     MakeStepLR(ieminus,inminus,rine,0);
  352.     PushState(igplus,Plus,-1);
  353.     MakeStep (seplus,igplus,rine);
  354.     MakeStep (seminus,igplus,rine);
  355.     MakeStep (leplus,igplus,rine);
  356.     MakeStep (feminus,igplus,rine);
  357.     PushState(feminus,Minus,-1);
  358.     MakeStepL(inminus,feminus,rie);
  359.     PushState(seminus,Minus,-1);
  360.     MakeStep (igminus,seminus,rie);
  361.     PushState(leplus,Plus,-1);
  362.     MakeStepL(inplus,leplus,rie);
  363.     PushState(seplus,Plus,-1);
  364.     MakeStep(igplus,seplus,rie);
  365.     PushState(igminus,Minus,-1);
  366.     MakeStep (seplus,igminus,rine);
  367.     MakeStep (seminus,igminus,rine);
  368.     MakeStep (leplus,igminus,rine);
  369.     MakeStep (feminus,igminus,rine);
  370.     igplus.back().UpdateScore(AddProbabilities(igplus.back().Score(),igminus.back().Score()));
  371.     const HMM_State* p = &igplus.back();
  372.     if (feminus.back().Score() > p->Score()) {
  373.         p = &feminus.back();
  374.     }
  375.     if (leplus.back().Score() > p->Score()) {
  376.         p = &leplus.back();
  377.     }
  378.     if (seplus.back().Score() > p->Score()) {
  379.         p = &seplus.back();
  380.     }
  381.     if (seminus.back().Score() > p->Score()) {
  382.         p = &seminus.back();
  383.     }
  384.     for (int ph = 0;  ph < 3;  ++ph) {
  385.         if (inplus[ph].back().Score() > p->Score()) {
  386.             p = &inplus[ph].back();
  387.         }
  388.         if (inminus[ph].back().Score() > p->Score()) {
  389.             p = &inminus[ph].back();
  390.         }
  391.         if (ieplus[ph].back().Score() > p->Score()) {
  392.             p = &ieplus[ph].back();
  393.         }
  394.         if (ieminus[ph].back().Score() > p->Score()) {
  395.             p = &ieminus[ph].back();
  396.         }
  397.         if (leminus[ph].back().Score() > p->Score()) {
  398.             p = &leminus[ph].back();
  399.         }
  400.         if (feplus[ph].back().Score() > p->Score()) {
  401.             p = &feplus[ph].back();
  402.         }
  403.     }
  404.     path = p;
  405. }
  406. template<class T> void Out(T t, int w, CNcbiOstream& to = cout)
  407. {
  408.     to.width(w);
  409.     to.setf(IOS_BASE::right,IOS_BASE::adjustfield);
  410.     to << t;
  411. }
  412. void Out(double t, int w, CNcbiOstream& to = cout, int prec = 1)
  413. {
  414.     to.width(w);
  415.     to.setf(IOS_BASE::right,IOS_BASE::adjustfield);
  416.     to.setf(IOS_BASE::fixed,IOS_BASE::floatfield);
  417.     to.precision(prec);
  418.     if (t > 1000000000) {
  419.         to << "+Inf";
  420.     } else if (t < -1000000000) {
  421.         to << "-Inf";
  422.     } else {
  423.         to << t;
  424.     }
  425. }
  426. inline char toACGT(int c)
  427. {
  428.     switch (c) {
  429.     case nA: 
  430.         return 'A';
  431.     case nC: 
  432.         return 'C';
  433.     case nG: 
  434.         return 'G';
  435.     case nT: 
  436.         return 'T';
  437.     case nN: 
  438.         return 'N';
  439.     }
  440. }
  441. int Parse::PrintGenes(CNcbiOstream& to, CNcbiOstream& toprot, bool complete) const
  442. {
  443.     enum {DNA_Align = 1, Prot_Align = 2 };
  444.     list<Gene> genes = GetGenes();
  445.     int right = seqscr.SeqMap(seqscr.SeqLen() - 1,true);
  446.     if (complete  &&  !genes.empty()  &&  !genes.back().RightComplete()) {
  447.         int partial_start = genes.back().front().Start();
  448.         genes.pop_back();
  449.         if ( !genes.empty() ) // end of the last complete gene
  450.         {
  451.             right = genes.back().back().Stop();
  452.         } else {
  453.             if (partial_start > seqscr.SeqMap(0,true) + 1000) {
  454.                 right = partial_start - 100;
  455.             } else {
  456.                 return -1;   // calling program MUST be aware of this!!!!!!!
  457.             }
  458.         }
  459.     }
  460.     to << "n" << seqscr.Contig() << '_' << seqscr.SeqMap(0,true) << '_' << right << "nn";
  461.     to << genes.size() << " genes foundn";
  462.     set<int> chain_id, prot_id;
  463.     for (list<Gene>::iterator it = genes.begin();  it != genes.end();  ++it) {
  464.         const Gene& gene = *it;
  465.         for (int i = 0;  i < gene.size();  ++i) {
  466.             ITERATE(set<int>, iter, gene[i].ChainID()) {
  467.                 chain_id.insert(*iter);
  468.             }
  469.             ITERATE(set<int>, iter, gene[i].ProtID()) {
  470.                 prot_id.insert(*iter);
  471.             }
  472.             //chain_id.insert(gene[i].ChainID().begin(), gene[i].ChainID().end());
  473.             //prot_id.insert(gene[i].ProtID().begin(),  gene[i].ProtID().end());
  474.         }
  475.     }
  476.     to << (chain_id.size() + prot_id.size()) << " alignments usedn";
  477.     int num = 0;
  478.     for (list<Gene>::iterator it = genes.begin();  it != genes.end();  ++it) {
  479.         ++num;
  480.         to << "nn";
  481.         Out(" ",11,to);
  482.         Out("Start",10,to);
  483.         Out("Stop",10,to);
  484.         Out("Length",7,to);
  485.         Out("Align",10,to);
  486.         Out("Prot",12,to);
  487.         Out("FShift",7,to);
  488.         to << endl;
  489.         const Gene& gene = *it;
  490.         int gene_start = -1;
  491.         int gene_stop;
  492.         int align_type = 0;
  493.         for (int i = 0;  i < gene.size();  ++i) {
  494.             const ExonData& exon = gene[i];
  495.             const TFrameShifts& fshifts = exon.ExonFrameShifts();
  496.             int estart = exon.Start();
  497.             if (gene_start < 0  &&  exon.Type() == ExonData::Cds) {
  498.                 gene_start = estart;
  499.             }
  500.             if ( !exon.ChainID().empty() ) {
  501.                 align_type = align_type|DNA_Align;
  502.             }
  503.             if ( !exon.ProtID().empty() ) {
  504.                 align_type = align_type|Prot_Align;
  505.             }
  506.             for (int k = 0;  k < fshifts.size();  ++k) {
  507.                 int estop = fshifts[k].Loc() - 1;
  508.                 Out(num,4,to);
  509.                 Out((exon.Type() == ExonData::Cds) ? "CDS" : "UTR",5,to); 
  510.                 Out((gene.Strand() == Plus) ? '+' : '-',2,to);
  511.                 Out(estart,10,to);
  512.                 Out(estop,10,to);
  513.                 Out(estop - estart + 1,7,to);
  514.                 if (exon.ChainID().empty()) {
  515.                     Out("-",10,to);
  516.                 } else {
  517.                     Out(*exon.ChainID().begin(),10,to);
  518.                 }
  519.                 if (exon.ProtID().empty()) {
  520.                     Out("-",12,to);
  521.                 } else {
  522.                     Out(*exon.ProtID().begin(),12,to);
  523.                 }
  524.                 if (fshifts[k].IsInsertion()) {
  525.                     Out("+",7,to);
  526.                     estart = estop;
  527.                 } else {
  528.                     Out("-",7,to);
  529.                     estart = estop + 2;
  530.                 }
  531.                 to << endl;
  532.             }
  533.             int estop = exon.Stop();
  534.             Out(num,4,to);
  535.             Out((exon.Type() == ExonData::Cds) ? "CDS" : "UTR",5,to); 
  536.             Out((gene.Strand() == Plus) ? '+' : '-',2,to);
  537.             Out(estart,10,to);
  538.             Out(estop,10,to);
  539.             Out(estop - estart + 1,7,to);
  540.             if (exon.ChainID().empty()) {
  541.                 Out("-",10,to);
  542.             } else {
  543.                 Out(*exon.ChainID().begin(),10,to);
  544.             }
  545.             if (exon.ProtID().empty()) {
  546.                 Out("-",12,to);
  547.             } else {
  548.                 Out(*exon.ProtID().begin(),12,to);
  549.             }
  550.             Out("*",7,to);
  551.             to << endl;
  552.             if (exon.Type() == ExonData::Cds) {
  553.                 gene_stop = estop;
  554.             }
  555.         }   
  556.         toprot << '>' << seqscr.Contig() << "_" 
  557.             << gene_start << "_" 
  558.             << gene_stop << "_"
  559.             << ((gene.Strand() == Plus) ? "plus" : "minus") << "_"
  560.             << align_type << endl;
  561.         const IVec& cds = gene.CDS();
  562.         int i;
  563.         for (i = 0;  i < cds.size() - 2;  i +=3) {
  564.             toprot << aa_table[cds[i]*25 + cds[i + 1]*5 + cds[i + 2]];
  565.             if ((i + 3)%150 == 0) {
  566.                 toprot << endl;
  567.             }
  568.         }
  569.         if (i%150 != 0) {
  570.             toprot << endl;
  571.         }
  572.         //      for (i = 0;  i < cds.size();  ++i)
  573.         //      {
  574.         //          toprot << toACGT(cds[i]);
  575.         //          if ((i + 3)%50 == 0) toprot << endl;
  576.         //      }
  577.         //      if (i%50 != 0) toprot << endl;
  578.     }
  579.     return right;
  580. }
  581. /*
  582. int Parse::PrintGenes(CNcbiOstream& to, CNcbiOstream& toprot, bool complete) const
  583. {
  584.     const char* aa_table = "KNKNXTTTTTRSRSXIIMIXXXXXXQHQHXPPPPPRRRRRLLLLLXXXXXEDEDXAAAAAGGGGGVVVVVXXXXX * Y*YXSSSSS * CWCXLFLFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  585.     const HMM_State* plast = Path();
  586.     if (complete  &&  dynamic_cast<const Intron*>(plast)) {
  587.         while (!dynamic_cast<const Intergenic*>(plast)) {
  588.             plast = plast->LeftState();
  589.         }
  590.         if ( !plast->LeftState() ) {
  591.             return plast->Start() + seqscr.SeqMap(0,true) - 1;
  592.         } else {
  593.             plast = plast->LeftState();
  594.         }
  595.     }
  596.     const CClusterSet& algns = seqscr.Alignments();
  597.     int right = seqscr.SeqMap(plast->Stop(),false);  // either end of chunk or and of last complete gene and its alignments
  598.     for (CClusterSet::ConstIt it = algns.begin();  it != algns.end();  ++it) {
  599.         if (it->Limits().Include(right)) {
  600.             right = it->Limits().second;
  601.         }
  602.     }
  603.     to << "n" << seqscr.Contig() << '_' << seqscr.SeqMap(0,true) << '_' << right << "nn";
  604.     vector<const Exon*> states;
  605.     const Exon* pe;
  606.     int gennum = 0;
  607.     for (const HMM_State* p = plast;  p != 0;  p = p->LeftState()) {
  608.         if (pe = dynamic_cast<const Exon*>(p)) {
  609.             states.push_back(pe);
  610.         }
  611.         if ( !states.empty() ) {
  612.             if ( !p->LeftState()  ||  dynamic_cast<const Intergenic*>(p) ) {
  613.                 ++gennum;
  614.             }
  615.         }
  616.     }
  617.     reverse(states.begin(),states.end());
  618.     int algnum = 0, algused = 0;
  619.     IPair chunk(seqscr.SeqMap(0,true),seqscr.SeqMap(seqscr.SeqLen() - 1,false));
  620.     for (CClusterSet::ConstIt it = algns.begin();  it != algns.end();  ++it) {
  621.         IPair lim = it->Limits();
  622.         if (lim.Intersect(chunk)) {
  623.             algnum += it->size();
  624.         }
  625.         for (int i = 0;  i < states.size();  ++i) {
  626.             int a = seqscr.SeqMap(states[i]->Start(),true);
  627.             int b = seqscr.SeqMap(states[i]->Stop(),false);
  628.             IPair exon(a,b);
  629.             if (exon.Intersect(lim)) {
  630.                 algused += it->size();
  631.                 break;
  632.             }
  633.         }
  634.     }
  635.     IVec ids(states.size(),0), prot_ids(states.size(),0);
  636.     for (int i = 0;  i < states.size();  ++i) {
  637.         int a = seqscr.SeqMap(states[i]->Start(),true);
  638.         int b = seqscr.SeqMap(states[i]->Stop(),false);
  639.         IPair exon(a,b);
  640.         for (CClusterSet::ConstIt cls_it = algns.begin();  cls_it != algns.end();  ++cls_it) {
  641.             for (CCluster::ConstIt it = cls_it->begin();  it != cls_it->end();  ++it)
  642.             {
  643.                 const AlignVec& al = *it;
  644.                 for (int j = 0;  j < al.size();  ++j) {
  645.                     if (exon.Intersect(al[j])) {
  646.                         if (al.Type() == AlignVec::Prot) {
  647.                             prot_ids[i] = al.ID();
  648.                         } else {
  649.                             ids[i] = al.ID();
  650.                             if (exon.first != al[j].first  ||  exon.second != al[j].second) {
  651.                                 ids[i] = -ids[i];
  652.                             }
  653.                         }
  654.                     }
  655.                 }
  656.             }
  657.         }
  658.     }
  659.     to << gennum << " genes foundn";
  660.     to << algused << " alignments used out of " << algnum << endl;
  661.     if (gennum == 0) {
  662.         return seqscr.SeqMap(plast->Stop(),false);
  663.     }
  664.     IVec cds;
  665.     int num = 0;
  666.     double gene_fscore, left_score;
  667.     int gene_start, gene_stop, align_type;
  668.     enum {DNA_Align = 1, Prot_Align = 2 };
  669.     for (int i = 0;  i < states.size();  ++i) {
  670.         pe = states[i];
  671.         int shift = 0;
  672.         if (i == 0  ||  
  673.             dynamic_cast<const SingleExon*>(pe)  ||  
  674.             (pe->isPlus()  &&  dynamic_cast<const FirstExon*>(pe))  ||  
  675.             (pe->isMinus()  &&  dynamic_cast<const LastExon*>(pe)))
  676.         {
  677.             gene_start = seqscr.SeqMap(pe->Start(),true);
  678.             ++num;
  679.             to << "nn";
  680.             Out(" ",19,to);
  681.             Out("Start",10,to);
  682.             Out("Stop",10,to);
  683.             Out("Length",7,to);
  684.             Out("Align",10,to);
  685.             Out("Prot",12,to);
  686.             Out("FShift",7,to);
  687.             to << endl;
  688.             left_score = pe->LeftState()->Score();
  689.             cds.clear();
  690.             const Intron* pi = dynamic_cast<const Intron*>(pe->LeftState());
  691.             if (pi != 0) {
  692.                 int ph = pi->Phase();
  693.                 if (pe->isPlus()) {
  694.                     shift = (3 - ph)%3;
  695.                 } else {
  696.                     shift = ph;
  697.                 }
  698.             }
  699.             align_type = 0;
  700.         }
  701.         //If first / last base is insertion, this information is lost
  702.         vector<IPair> subexons;
  703.         int a = seqscr.SeqMap(pe->Start(),true);
  704.         int b = a;
  705.         for (int k = pe->Start() + 1;  k <= pe->Stop();  ++k) {
  706.             int c = seqscr.SeqMap(k,false);
  707.             if (c == b) {
  708.                 subexons.push_back(IPair(a,b));
  709.                 a = b;
  710.             }
  711.             if (c == b + 2) {
  712.                 subexons.push_back(IPair(a,b));
  713.                 a = c;
  714.             }
  715.             b = c;
  716.         }
  717.         subexons.push_back(IPair(a,b));
  718.         for (int k = 0;  k < subexons.size();  ++k) {
  719.             int a = subexons[k].first;
  720.             int b = subexons[k].second;
  721.             Out(num,4,to);
  722.             Out(pe->GetStateName(),13,to);
  723.             Out(pe->isPlus() ? '+' : '-',2,to);
  724.             Out(a,10,to);
  725.             Out(b,10,to);
  726.             Out(b - a+1,7,to);
  727.             if (ids[i]) {
  728.                 align_type = align_type|DNA_Align;
  729.                 Out(abs(ids[i]),9,to);
  730.                 to << ((ids[i] > 0) ? ' ' : '*');
  731.             } else {
  732.                 Out("-",9,to);
  733.                 to << ' ';
  734.             }
  735.             if (prot_ids[i]) {
  736.                 align_type = align_type|Prot_Align;
  737.                 Out(prot_ids[i],12,to);
  738.             } else {
  739.                 Out("-",12,to);
  740.             }
  741.             if (k != 0) {
  742.                 if (a == subexons[k - 1].second) {
  743.                     Out("+",7,to);
  744.                 } else if (a == subexons[k - 1].second + 2) {
  745.                     Out("-",7,to);
  746.                 } else {
  747.                     Out("*",7,to);
  748.                 }
  749.             } else {
  750.                 Out("*",7,to);
  751.             }
  752.             to << endl;
  753.         }
  754.         bool last = false;
  755.         if (i == states.size() - 1  ||  
  756.             dynamic_cast<const SingleExon*>(pe)  ||  
  757.             (pe->isPlus()  &&  dynamic_cast<const LastExon*>(pe))  ||  
  758.             (pe->isMinus()  &&  dynamic_cast<const FirstExon*>(pe)))
  759.         {
  760.             last = true;
  761.             gene_stop = seqscr.SeqMap(pe->Stop(),false);
  762.         }
  763.         copy(seqscr.SeqPtr(pe->Start() + shift,Plus),
  764.              seqscr.SeqPtr(pe->Stop() + 1,Plus),back_inserter(cds));
  765.         if (last) {
  766.             to << endl;
  767.             cds.resize(cds.size() - cds.size()%3);
  768.             if (pe->isMinus()) {
  769.                 for (int i = 0;  i < cds.size();  ++i) cds[i] = toMinus[cds[i]];
  770.                 reverse(cds.begin(),cds.end());
  771.             }
  772.             toprot << '>' << seqscr.Contig() << "_" 
  773.                 << gene_start << "_" 
  774.                 << gene_stop << "_"
  775.                 << (pe->isPlus() ? "plus" : "minus") << "_"
  776.                 << align_type << endl;
  777.             int i;
  778.             for (i = 0;  i < cds.size() - 2;  i +=3) {
  779.                 toprot << aa_table[cds[i]*25 + cds[i + 1]*5 + cds[i + 2]];
  780.                 if ((i + 3)%150 == 0) {
  781.                     toprot << endl;
  782.                 }
  783.             }
  784.             if (i%150 != 0) {
  785.                 toprot << endl;
  786.             }
  787.         }
  788.     }
  789.     return right;
  790. }
  791. */
  792. list<Gene> Parse::GetGenes() const
  793. {
  794.     list<Gene> genes;
  795.     const CClusterSet& cls = seqscr.Alignments();
  796.     if (dynamic_cast<const Intron*>(Path())) {
  797.         genes.push_front(Gene(Path()->Strand(),false,false));
  798.     }
  799.     for (const HMM_State* p = Path();  p != 0;  p = p->LeftState()) {
  800.         if (const Exon* pe = dynamic_cast<const Exon*>(p)) {
  801.             bool stopcodon = false;
  802.             bool startcodon = false;
  803.             if (dynamic_cast<const SingleExon*>(pe)) {
  804.                 genes.push_front(Gene(pe->Strand(),true,true));
  805.                 startcodon = true;
  806.                 stopcodon = true;
  807.             } else if (dynamic_cast<const LastExon*>(pe)) {
  808.                 if (pe->isPlus()) {
  809.                     genes.push_front(Gene(pe->Strand(),false,true));
  810.                 } else {
  811.                     genes.front().leftend = true;
  812.                 }
  813.                 stopcodon = true;
  814.             } else if (dynamic_cast<const FirstExon*>(pe)) {
  815.                 if (pe->isMinus()) {
  816.                     genes.push_front(Gene(pe->Strand(),false,true));
  817.                 } else {
  818.                     genes.front().leftend = true;
  819.                 }
  820.                 startcodon = true;
  821.             }
  822.             Gene& curgen = genes.front();
  823.             int estart = pe->Start();
  824.             int estop = pe->Stop();
  825.             if (pe->isPlus()) {
  826.                 int ph = (pe->Phase() - estop + estart)%3;
  827.                 if (ph < 0) {
  828.                     ph += 3;
  829.                 }
  830.                 curgen.cds_shift = ph;
  831.             } else if (curgen.empty()) {
  832.                 curgen.cds_shift = pe->Phase();
  833.             }
  834.             if (pe->isMinus()  &&  startcodon) {
  835.                 curgen.cds.push_back(nT);
  836.                 curgen.cds.push_back(nA);
  837.                 curgen.cds.push_back(nC);
  838.             }
  839.             for (int i = estop;  i >= estart;  --i) {
  840.                 curgen.cds.push_back(*seqscr.SeqPtr(i,Plus));
  841.             }
  842.             if (pe->isPlus()  &&  startcodon) {
  843.                 curgen.cds.push_back(nG);
  844.                 curgen.cds.push_back(nT);
  845.                 curgen.cds.push_back(nA);
  846.             }
  847.             int a = seqscr.SeqMap(estart,true);
  848.             bool a_insertion = (estart != seqscr.RevSeqMap(a,true));
  849.             int b = seqscr.SeqMap(estop,false);
  850.             bool b_insertion = (estop != seqscr.RevSeqMap(b,true));
  851.             pair<CClusterSet::ConstIt,CClusterSet::ConstIt> lim = cls.equal_range(CCluster(a,b));
  852.             CClusterSet::ConstIt first = lim.first;
  853.             CClusterSet::ConstIt last = lim.second;
  854.             if (lim.first != lim.second) {
  855.                 --last;
  856.             }
  857.             int lastid = 0;
  858.             int margin = numeric_limits<int>::min();   // difference between end of exon and end of alignment exon
  859.             bool rightexon = false;
  860.             if (((startcodon  &&  pe->isMinus())  ||  (stopcodon  &&  pe->isPlus()))  &&  lim.first != lim.second)   // rightside UTR
  861.             {
  862.                 for (CCluster::ConstIt it = last->begin();  it != last->end();  ++it) {
  863.                     const AlignVec& algn = *it;
  864.                     if (algn.Type() == AlignVec::Prot) {
  865.                         continue;
  866.                     }
  867.                     for (int i = algn.size() - 1;  i >= 0;  --i) {
  868.                         if (b < algn[i].first) {
  869.                             curgen.push_back(ExonData(algn[i].first,algn[i].second,ExonData::Utr));
  870.                             curgen.back().chain_id.insert(algn.ID()); 
  871.                             rightexon = true;
  872.                         } else if (algn[i].second >= a  &&  algn[i].second - b > margin) {
  873.                             margin = algn[i].second - b;
  874.                             lastid = algn.ID();
  875.                         }
  876.                     }
  877.                 }
  878.             }
  879.             int remain = 0;
  880.             if ((pe->isMinus()  &&  startcodon)  ||  (pe->isPlus()  &&  stopcodon))   // start / stop position correction
  881.             {
  882.                 if (margin >= 3) {
  883.                     b += 3;
  884.                     margin -= 3;
  885.                 } else if (margin >= 0  &&  rightexon) {
  886.                     b += margin;
  887.                     remain = 3 - margin;
  888.                     margin = 0;
  889.                 } else {
  890.                     b += 3;
  891.                     margin = 0;
  892.                 }
  893.             }
  894.             if (margin > 0) {
  895.                 curgen.push_back(ExonData(b + 1,b + margin,ExonData::Utr)); 
  896.                 curgen.back().chain_id.insert(lastid); 
  897.             } else if (remain > 0) {
  898.                 ExonData& e = curgen.back();
  899.                 int aa = e.start;
  900.                 e.start += remain;
  901.                 int bb = aa + remain - 1;
  902.                 ExonData er(aa,bb,ExonData::Cds);
  903.                 er.chain_id = e.chain_id;
  904.                 curgen.push_back(er);
  905.             }
  906.             curgen.push_back(ExonData(a,b,ExonData::Cds));
  907.             ExonData& exon = curgen.back();
  908.             margin = numeric_limits<int>::min();
  909.             bool leftexon = false;
  910.             lastid = 0;
  911.             for (CClusterSet::ConstIt cls_it = lim.first;  cls_it != lim.second;  ++cls_it) {
  912.                 for (CCluster::ConstIt it = cls_it->begin();  it != cls_it->end();  ++it)
  913.                 {
  914.                     const AlignVec& algn = *it;
  915.                     for (int i = 0;  i < algn.size();  ++i) {
  916.                         if (exon.stop < algn[i].first) {
  917.                             break;
  918.                         } else if (algn[i].second < exon.start) {
  919.                             leftexon = true;
  920.                             continue;
  921.                         } else if (algn.Type() == AlignVec::Prot) {
  922.                             exon.prot_id.insert(algn.ID()); 
  923.                         } else {
  924.                             exon.chain_id.insert(algn.ID());
  925.                             if (a - algn[i].first > margin) {
  926.                                 margin = a - algn[i].first;
  927.                                 lastid = algn.ID();
  928.                             }
  929.                         }
  930.                     }
  931.                 }
  932.             }
  933.             const TFrameShifts& fs = seqscr.SeqFrameShifts();
  934.             for (int i = 0;  i < fs.size();  ++i) {
  935.                 if ((fs[i].Loc() == a  &&  a_insertion)  ||  // exon starts from insertion
  936.                     (fs[i].Loc() == b + 1  &&  b_insertion)  ||  // exon ends by insertion
  937.                     (fs[i].Loc() <= b  &&  fs[i].Loc() > a)) {
  938.                     exon.fshifts.push_back(fs[i]);
  939.                 }
  940.             }
  941.             remain = 0;
  942.             if ((pe->isPlus()  &&  startcodon)  ||  (pe->isMinus()  &&  stopcodon))   // start / stop position correction
  943.             {
  944.                 if (margin >= 3) {
  945.                     exon.start -= 3;
  946.                     margin -= 3;
  947.                 } else if (margin >= 0  &&  leftexon) {
  948.                     exon.start -= margin;
  949.                     remain = 3 - margin;
  950.                     margin = 0;
  951.                 } else {
  952.                     exon.start -= 3;
  953.                     margin = 0;
  954.                 }
  955.             }
  956.             if (((startcodon  &&  pe->isPlus())  ||  (stopcodon  &&  pe->isMinus()))  &&  lim.first != lim.second)   // lefttside UTR
  957.             {
  958.                 int estart = exon.start;
  959.                 if (margin > 0) {
  960.                     curgen.push_back(ExonData(estart - margin,estart - 1,ExonData::Utr)); 
  961.                     curgen.back().chain_id.insert(lastid); 
  962.                 }
  963.                 for (CCluster::ConstIt it = first->begin();  it != first->end();  ++it) {
  964.                     const AlignVec& algn = *it;
  965.                     if (algn.Type() == AlignVec::Prot) {
  966.                         continue;
  967.                     }
  968.                     for (int i = algn.size() - 1;  i >= 0;  --i) {
  969.                         if (estart > algn[i].second) {
  970.                             int aa = algn[i].first;
  971.                             int bb = algn[i].second;
  972.                             if (remain > 0) {
  973.                                 curgen.push_back(ExonData(bb - remain + 1,bb,ExonData::Cds));
  974.                                 curgen.back().chain_id.insert(algn.ID()); 
  975.                                 bb -= remain;
  976.                                 remain = 0;
  977.                             }
  978.                             curgen.push_back(ExonData(aa,bb,ExonData::Utr)); 
  979.                             curgen.back().chain_id.insert(algn.ID()); 
  980.                         }
  981.                     }
  982.                 }
  983.             }
  984.         }
  985.     }
  986.     for (list<Gene>::iterator it = genes.begin();  it != genes.end();  ++it) {
  987.         Gene& g = *it;
  988.         reverse(g.begin(),g.end());
  989.         if (g.Strand() == Plus) {
  990.             reverse(g.cds.begin(),g.cds.end());
  991.         } else {
  992.             for (int i = 0;  i < g.cds.size();  ++i) {
  993.                 g.cds[i] = toMinus[g.cds[i]];
  994.             }
  995.         }
  996.     }
  997.     return genes;
  998. }
  999. void Parse::PrintInfo() const
  1000. {
  1001.     vector<const HMM_State*> states;
  1002.     for (const HMM_State* p = Path();  p != 0;  p = p->LeftState()) states.push_back(p);
  1003.     reverse(states.begin(),states.end());
  1004.     Out(" ",15);
  1005.     Out("Start",8);
  1006.     Out("Stop",8);
  1007.     Out("Score",8);
  1008.     Out("BrScr",8);
  1009.     Out("LnScr",8);
  1010.     Out("RgnScr",8);
  1011.     Out("TrmScr",8);
  1012.     Out("AccScr",8);
  1013.     cout << endl;
  1014.     for (int i = 0;  i < states.size();  ++i) {
  1015.         const HMM_State* p = states[i];
  1016.         if (dynamic_cast<const Intergenic*>(p)) {
  1017.             cout << endl;
  1018.         }
  1019.         Out(p->GetStateName(),13);
  1020.         Out(p->isPlus() ? '+' : '-',2);
  1021.         int a = seqscr.SeqMap(p->Start(),true);
  1022.         int b = seqscr.SeqMap(p->Stop(),false);
  1023.         Out(a,8);
  1024.         Out(b,8);
  1025.         StateScores sc = p->GetStateScores();
  1026.         Out(sc.score,8);
  1027.         Out(sc.branch,8);
  1028.         Out(sc.length,8);
  1029.         Out(sc.region,8);
  1030.         Out(sc.term,8);
  1031.         Out(p->Score(),8);
  1032.         cout << endl;
  1033.     }
  1034. }
  1035. void LogicalCheck(const HMM_State& st, const SeqScores& ss)
  1036. {
  1037.     typedef const Intergenic* Ig;
  1038.     typedef const Intron* I;
  1039.     typedef const FirstExon* FE;
  1040.     typedef const InternalExon* IE;
  1041.     typedef const LastExon* LE;
  1042.     typedef const SingleExon* SE;
  1043.     typedef const Exon* E;
  1044.     bool out;
  1045.     int phase,strand;
  1046.     vector< pair<int,int> > exons;
  1047.     for (const HMM_State* state = &st;  state != 0;  state = state->LeftState()) {
  1048.         const HMM_State* left = state->LeftState();
  1049.         if (left == 0) {
  1050.             if ( !dynamic_cast<Ig>(state)  &&  !dynamic_cast<I>(state) ) {
  1051.                 NCBI_THROW(CGnomonException, eGenericError,
  1052.                            "GNOMON: Logical error 1");
  1053.             }
  1054.             out = true;
  1055.         } else if (dynamic_cast<Ig>(state)) {
  1056.             if ( !dynamic_cast<SE>(left)  &&  
  1057.                  !(dynamic_cast<LE>(left)  &&  left->isPlus())  &&  
  1058.                  !(dynamic_cast<FE>(left)  &&  left->isMinus()) ) {
  1059.                 NCBI_THROW(CGnomonException, eGenericError,
  1060.                            "GNOMON: Logical error 2");
  1061.             }
  1062.             out = true;
  1063.         } else if (I ps = dynamic_cast<I>(state)) {
  1064.             E p;
  1065.             int ph = -1;
  1066.             if (((p = dynamic_cast<FE>(left))  &&  left->isPlus())  ||  
  1067.                 ((p = dynamic_cast<LE>(left))  &&  left->isMinus())  ||  
  1068.                 (p = dynamic_cast<IE>(left))) {
  1069.                 ph = p->Phase();
  1070.             }
  1071.             if ((ph < 0)  ||  (ps->Strand() != left->Strand())  ||  
  1072.                 (ps->isPlus()  &&  (ph + 1)%3 != ps->Phase())  ||  
  1073.                 (ps->isMinus()  &&  ph != ps->Phase())) {
  1074.                 NCBI_THROW(CGnomonException, eGenericError,
  1075.                            "GNOMON: Logical error 3");
  1076.             }
  1077.             out = false;
  1078.         } else if (SE ps = dynamic_cast<SE>(state)) {
  1079.             if ( !(dynamic_cast<Ig>(left)  &&  ps->Strand() == left->Strand()) ) {
  1080.                 NCBI_THROW(CGnomonException, eGenericError,
  1081.                            "GNOMON: Logical error 4");
  1082.             }
  1083.             int a = ps->Start(), b = ps->Stop();
  1084.             if ((b - a+1)%3  ||  
  1085.                 (ps->isPlus()  &&  (!ss.isStart(a,Plus)  ||  !ss.isStop(b + 1,Plus)))  ||  
  1086.                 (ps->isMinus()  &&  (!ss.isStart(b,Minus)  ||  !ss.isStop(a - 1,Minus))))  {
  1087.                 NCBI_THROW(CGnomonException, eGenericError,
  1088.                            "GNOMON: Logical error 5");
  1089.             }
  1090.         } else if (FE ps = dynamic_cast<FE>(state)) {
  1091.             I p;
  1092.             if ((ps->Strand() != left->Strand())  ||  
  1093.                 (!(dynamic_cast<Ig>(left)  &&  ps->isPlus())  &&  
  1094.                  !((p = dynamic_cast<I>(left))  &&  ps->isMinus()))) {
  1095.                 NCBI_THROW(CGnomonException, eGenericError,
  1096.                            "GNOMON: Logical error 6");
  1097.             }
  1098.             int a = ps->Start(), b = ps->Stop();
  1099.             if (ps->isPlus()) {
  1100.                 if (ps->Phase() != (b - a)%3) {
  1101.                     NCBI_THROW(CGnomonException, eGenericError,
  1102.                                "GNOMON: Logical error 7");
  1103.                 }
  1104.             } else {
  1105.                 if (p->Phase() != (b + 1-a)%3) {
  1106.                     NCBI_THROW(CGnomonException, eGenericError,
  1107.                                "GNOMON: Logical error 8");
  1108.                 }
  1109.             }
  1110.             //          if ((ps->isPlus()  &&  (!ss.isStart(a,Plus)  ||  !ss.isGT(b + 1,Plus)))  ||  
  1111.             //             (ps->isMinus()  &&  (!ss.isStart(b,Minus)  ||  !ss.isGT(a - 1,Minus)))) 
  1112.             //          { cout << "Logical error9n"; exit(1); }
  1113.         } else if (IE ps = dynamic_cast<IE>(state)) {
  1114.             I p;
  1115.             if ((ps->Strand() != left->Strand())  ||  
  1116.                 !(p = dynamic_cast<I>(left))) {
  1117.                 NCBI_THROW(CGnomonException, eGenericError,
  1118.                            "GNOMON: Logical error 10");
  1119.             }
  1120.             int a = ps->Start(), b = ps->Stop();
  1121.             if (ps->isPlus()) {
  1122.                 if (ps->Phase() != (p->Phase() + b-a)%3) {
  1123.                     NCBI_THROW(CGnomonException, eGenericError,
  1124.                                "GNOMON: Logical error 11");
  1125.                 }
  1126.             } else {
  1127.                 if (p->Phase() != (ps->Phase() + b+1 - a)%3) {
  1128.                     NCBI_THROW(CGnomonException, eGenericError,
  1129.                                "GNOMON: Logical error 12");
  1130.                 }
  1131.             }
  1132.             //          if ((ps->isPlus()  &&  (!ss.isAG(a - 1,Plus)  ||  !ss.isGT(b + 1,Plus)))  ||  
  1133.             //             (ps->isMinus()  &&  (!ss.isAG(b + 1,Minus)  ||  !ss.isGT(a - 1,Minus)))) 
  1134.             //          { cout << "Logical error13n"; exit(1); }
  1135.         } else if (LE ps = dynamic_cast<LE>(state)) {
  1136.             I p;
  1137.             if ((ps->Strand() != left->Strand())  ||  
  1138.                 (!(dynamic_cast<Ig>(left)  &&  ps->isMinus())  &&  
  1139.                  !((p = dynamic_cast<I>(left))  &&  ps->isPlus()))) {
  1140.                 NCBI_THROW(CGnomonException, eGenericError,
  1141.                            "GNOMON: Logical error 14");
  1142.             }
  1143.             int a = ps->Start(), b = ps->Stop();
  1144.             if (ps->isPlus()) {
  1145.                 if ((p->Phase() + b - a) % 3 != 2) {
  1146.                     NCBI_THROW(CGnomonException, eGenericError,
  1147.                                "GNOMON: Logical error 15");
  1148.                 }
  1149.             } else {
  1150.                 if ((ps->Phase() + b-a)%3 != 2) {
  1151.                     NCBI_THROW(CGnomonException, eGenericError,
  1152.                                "GNOMON: Logical error 16");
  1153.                 }
  1154.             }
  1155.             //          if ((ps->isPlus()  &&  (!ss.isAG(a - 1,Plus)  ||  !ss.isStop(b + 1,Plus)))  ||  
  1156.             //             (ps->isMinus()  &&  (!ss.isStop(a - 1,Minus)  ||  !ss.isAG(b + 1,Minus)))) 
  1157.             //          { cout << "Logical error17n"; exit(1); }
  1158.         }
  1159.         if (E ps = dynamic_cast<E>(state)) {
  1160.             phase = ps->Phase();
  1161.             strand = ps->Strand();
  1162.             exons.push_back(make_pair(ps->Start(),ps->Stop()));
  1163.             out = false;
  1164.         }
  1165.         if (out  &&  !exons.empty()) {
  1166.             IVec seq;
  1167.             if (strand == Plus) {
  1168.                 for (int i = exons.size() - 1;  i >= 0;  --i) {
  1169.                     int a = exons[i].first;
  1170.                     int b = exons[i].second;
  1171.                     seq.insert(seq.end(),ss.SeqPtr(a,Plus),ss.SeqPtr(b,Plus) + 1);
  1172.                 }
  1173.                 phase = (phase - exons.back().second + exons.back().first)%3;
  1174.                 if (phase < 0) {
  1175.                     phase += 3;
  1176.                 }
  1177.             } else {
  1178.                 for (int i = 0;  i < exons.size();  ++i) {
  1179.                     int b = exons[i].first;
  1180.                     int a = exons[i].second;
  1181.                     seq.insert(seq.end(),ss.SeqPtr(a,Minus),ss.SeqPtr(b,Minus) + 1);
  1182.                 }
  1183.                 int l = seq.size() - 1;
  1184.                 phase = (phase + exons.back().second - exons.back().first - l)%3;
  1185.                 if (phase < 0) {
  1186.                     phase += 3;
  1187.                 }
  1188.             }
  1189.             for (int i = (3 - phase) % 3;  i + 2 < seq.size();  i += 3) {
  1190.                 if ((seq[i] == nT  &&  seq[i + 1] == nA  &&  seq[i + 2] == nA)  ||  
  1191.                     (seq[i] == nT  &&  seq[i + 1] == nA  &&  seq[i + 2] == nG)  ||  
  1192.                     (seq[i] == nT  &&  seq[i + 1] == nG  &&  seq[i + 2] == nA))  {
  1193.                     NCBI_THROW(CGnomonException, eGenericError,
  1194.                                "GNOMON: Logical error 18");
  1195.                 }
  1196.             }
  1197.             exons.clear();
  1198.             //          cout << "Gene is clearedn";
  1199.         }
  1200.     }
  1201. }
  1202. END_NCBI_SCOPE
  1203. /*
  1204.  * ===========================================================================
  1205.  * $Log: parse.cpp,v $
  1206.  * Revision 1000.2  2004/06/01 18:08:37  gouriano
  1207.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  1208.  *
  1209.  * Revision 1.3  2004/05/21 21:41:03  gorelenk
  1210.  * Added PCH ncbi_pch.hpp
  1211.  *
  1212.  * Revision 1.2  2003/11/06 15:02:21  ucko
  1213.  * Use iostream interface from ncbistre.hpp for GCC 2.95 compatibility.
  1214.  *
  1215.  * Revision 1.1  2003/10/24 15:07:25  dicuccio
  1216.  * Initial revision
  1217.  *
  1218.  * ===========================================================================
  1219.  */