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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: validerror_align.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:47:45  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: validerror_align.cpp,v 1000.1 2004/06/01 19:47:45 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:  Jonathan Kans, Clifford Clausen, Aaron Ucko......
  35.  *
  36.  * File Description:
  37.  *   validation of seq_align
  38.  *   .......
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <objects/seqalign/Seq_align.hpp>
  44. #include <objects/seqalign/Dense_diag.hpp>
  45. #include <objects/seqalign/Dense_seg.hpp>
  46. #include <objects/seqalign/Packed_seg.hpp>
  47. #include <objects/seqalign/Seq_align_set.hpp>
  48. #include <objects/seqalign/Std_seg.hpp>
  49. #include <objmgr/util/sequence.hpp>
  50. #include <map>
  51. #include <vector>
  52. #include <algorithm>
  53. #include "validatorp.hpp"
  54. BEGIN_NCBI_SCOPE
  55. BEGIN_SCOPE(objects)
  56. BEGIN_SCOPE(validator)
  57. USING_SCOPE(sequence);
  58. // ================================  Public  ================================
  59. CValidError_align::CValidError_align(CValidError_imp& imp) :
  60.     CValidError_base(imp)
  61. {
  62. }
  63. CValidError_align::~CValidError_align(void)
  64. {
  65. }
  66. void CValidError_align::ValidateSeqAlign(const CSeq_align& align)
  67. {
  68.     const CSeq_align::TSegs& segs = align.GetSegs();
  69.     CSeq_align::C_Segs::E_Choice segtype = segs.Which();
  70.     switch ( segtype ) {
  71.     
  72.     case CSeq_align::C_Segs::e_Dendiag:
  73.         x_ValidateDendiag(segs.GetDendiag(), align);
  74.         break;
  75.     case CSeq_align::C_Segs::e_Denseg:
  76.         x_ValidateDenseg(segs.GetDenseg(), align);
  77.         break;
  78.     case CSeq_align::C_Segs::e_Std:
  79.         x_ValidateStd(segs.GetStd(), align);
  80.         break;
  81.     case CSeq_align::C_Segs::e_Packed:
  82.         x_ValidatePacked(segs.GetPacked(), align);
  83.         break;
  84.     case CSeq_align::C_Segs::e_Disc:
  85.         // call recursively
  86.         ITERATE(CSeq_align_set::Tdata, sali, segs.GetDisc().Get()) {
  87.             ValidateSeqAlign(**sali);
  88.         }
  89.         return;
  90.     case CSeq_align::C_Segs::e_not_set:
  91.     default:
  92.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_Segtype,
  93.             "This alignment has undefined or unsupported Seq_align"
  94.             "segtype " + NStr::IntToString(segtype) + ".", align);
  95.         break;
  96.     }  // end of switch statement
  97. }
  98. // ================================  Private  ===============================
  99. void CValidError_align::x_ValidateDenseg
  100. (const TDenseg& denseg,
  101.  const CSeq_align& align)
  102. {
  103.     bool cont = true;
  104.     // assert dim >= 2
  105.     if ( !x_ValidateDim(denseg, align) ) {
  106.         return;
  107.     }
  108.     size_t dim     = denseg.GetDim();
  109.     size_t numseg  = denseg.GetNumseg();
  110.     // assert dim == Ids.size()
  111.     if ( dim != denseg.GetIds().size() ) {
  112.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  113.                 "Mismatch between specified dimension (" +
  114.                 NStr::UIntToString(dim) + 
  115.                 ") and number of Seq-ids (" + 
  116.                 NStr::UIntToString(denseg.GetIds().size()) + ")",
  117.                 align);
  118.         cont = false;
  119.     }
  120.     // assert numseg == Lens.size()
  121.     if ( numseg != denseg.GetLens().size() ) {
  122.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsNumsegMismatch,
  123.                 "Mismatch between specified numseg (" +
  124.                 NStr::UIntToString(numseg) + 
  125.                 ") and number of Lens (" + 
  126.                 NStr::UIntToString(denseg.GetLens().size()) + ")",
  127.                 align);
  128.         cont = false;
  129.     }
  130.     // assert dim * numseg == Starts.size()
  131.     if ( dim * numseg != denseg.GetStarts().size() ) {
  132.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsStartsMismatch,
  133.                 "The number of Starts (" + 
  134.                 NStr::UIntToString(denseg.GetStarts().size()) +
  135.                 ") does not match the expected size of dim * numseg (" +
  136.                 NStr::UIntToString(dim * numseg) + ")", align);
  137.         cont = false;
  138.     } 
  139.     if( cont ) {
  140.         x_ValidateStrand(denseg, align);
  141.         x_ValidateFastaLike(denseg, align);
  142.         x_ValidateSegmentGap(denseg, align);
  143.         
  144.         if ( m_Imp.IsRemoteFetch() ) {
  145.             x_ValidateSeqId(align);
  146.             x_ValidateSeqLength(denseg, align);
  147.         }
  148.     }
  149. }
  150. void CValidError_align::x_ValidatePacked
  151. (const TPacked& packed,
  152.  const CSeq_align& align)
  153. {
  154.     bool cont = true;
  155.     // assert dim >= 2
  156.     if ( !x_ValidateDim(packed, align) ) {
  157.         return;
  158.     }
  159.     size_t dim     = packed.GetDim();
  160.     size_t numseg  = packed.GetNumseg();
  161.     
  162.     // assert dim == Ids.size()
  163.     if ( dim != packed.GetIds().size() ) {
  164.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  165.             "Mismatch between specified dimension (" +
  166.             NStr::UIntToString(dim) + 
  167.             ") and number of Seq-ids (" + 
  168.             NStr::UIntToString(packed.GetIds().size()) + ")",
  169.             align);
  170.         cont = false;
  171.     }
  172.     
  173.     // assert numseg == Lens.size()
  174.     if ( numseg != packed.GetLens().size() ) {
  175.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  176.             "Mismatch between specified numseg (" +
  177.             NStr::UIntToString(numseg) + 
  178.             ") and number of Lens (" + 
  179.             NStr::UIntToString(packed.GetLens().size()) + ")",
  180.             align);
  181.         cont = false;
  182.     }
  183.     
  184.     // assert dim * numseg == Present.size()
  185.     if ( dim * numseg != packed.GetPresent().size() ) {
  186.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsPresentMismatch,
  187.                 "The number of Present (" + 
  188.                 NStr::UIntToString(packed.GetPresent().size()) +
  189.                 ") does not match the expected size of dim * numseg (" +
  190.                 NStr::UIntToString(dim * numseg) + ")", align);
  191.         cont = false;
  192.     } else {
  193.         // assert # of '1' bits in present == Starts.size()
  194.         size_t bits = x_CountBits(packed.GetPresent());
  195.         if ( bits != packed.GetStarts().size() ) {
  196.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsPresentStartsMismatch,
  197.                 "Starts does not have the same number of elements (" +
  198.                 NStr::UIntToString(packed.GetStarts().size()) + 
  199.                 ") as specified by Present (" + NStr::UIntToString(bits) +
  200.                 ")", align);
  201.             cont = false;
  202.         }
  203.         // assert # of '1' bits in present == Strands.size() (if exists)
  204.         if ( packed.IsSetStrands() ) {
  205.             if ( bits != packed.GetStarts().size() ) {
  206.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsPresentStrandsMismatch,
  207.                     "Strands does not have the same number of elements (" +
  208.                     NStr::UIntToString(packed.GetStrands().size()) +
  209.                     ") as specified by Present (" +
  210.                     NStr::UIntToString(bits) + ")", align);
  211.                 cont = false;
  212.             }
  213.         }
  214.     }
  215.     
  216.     if( cont ) {
  217.         x_ValidateStrand(packed, align);
  218.         x_ValidateFastaLike(packed, align);
  219.         x_ValidateSegmentGap(packed, align);
  220.         
  221.         if ( m_Imp.IsRemoteFetch() ) {
  222.             x_ValidateSeqId(align);
  223.             x_ValidateSeqLength(packed, align);
  224.         }
  225.     }
  226. }
  227. size_t CValidError_align::x_CountBits(const CPacked_seg::TPresent& present)
  228. {
  229.     size_t bits = 0;
  230.     ITERATE( CPacked_seg::TPresent, iter, present ) {
  231.         if ( *iter != 0 ) {
  232.             Uchar mask = 0x01;
  233.             for ( size_t i = 0; i < 7; ++i ) {
  234.                 bits += (*iter & mask) ? 1 : 0;
  235.                 mask = mask << 1;
  236.             }
  237.         }
  238.     }
  239.     return bits;
  240. }
  241. void CValidError_align::x_ValidateDendiag
  242. (const TDendiag& dendiags,
  243.  const CSeq_align& align)
  244. {
  245.     size_t num_dendiag = 0;
  246.     ITERATE( TDendiag, dendiag_iter, dendiags ) {
  247.         bool cont = true;
  248.         ++num_dendiag;
  249.         const CDense_diag& dendiag = **dendiag_iter;
  250.         size_t dim = dendiag.GetDim();
  251.         // assert dim >= 2
  252.         if ( !x_ValidateDim(dendiag, align, num_dendiag) ) {
  253.             continue;
  254.         }
  255.         // assert dim == Ids.size()
  256.         if ( dim != dendiag.GetIds().size() ) {
  257.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  258.                 "Mismatch between specified dimension (" +
  259.                 NStr::UIntToString(dim) + 
  260.                 ") and number of Seq-ids (" + 
  261.                 NStr::UIntToString(dendiag.GetIds().size()) + ") in dendiag " +
  262.                 NStr::UIntToString(num_dendiag), align);
  263.             cont = false;
  264.         }
  265.         // assert dim == Starts.size()
  266.         if ( dim != dendiag.GetStarts().size() ) {
  267.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  268.                 "Mismatch between specified dimension (" +
  269.                 NStr::UIntToString(dim) + 
  270.                 ") and number ofStarts (" + 
  271.                 NStr::UIntToString(dendiag.GetStarts().size()) + 
  272.                 ") in dendiag " + NStr::UIntToString(num_dendiag), align);
  273.             cont = false;
  274.         } 
  275.         // assert dim == Strands.size() (if exist)
  276.         if ( dendiag.IsSetStrands() ) {
  277.             if ( dim != dendiag.GetStrands().size() ) {
  278.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  279.                     "Mismatch between specified dimension (" +
  280.                     NStr::UIntToString(dim) + 
  281.                     ") and number of Strands (" + 
  282.                     NStr::UIntToString(dendiag.GetStrands().size()) + 
  283.                     ") in dendiag " + NStr::UIntToString(num_dendiag), align);
  284.                 cont = false;
  285.             } 
  286.         }
  287.         if ( cont ) {
  288.             if ( m_Imp.IsRemoteFetch() ) {
  289.                 x_ValidateSeqId(align);
  290.                 x_ValidateSeqLength(dendiag, num_dendiag, align);
  291.             }
  292.         }
  293.     }
  294. }
  295. void CValidError_align::x_ValidateStd
  296. (const TStd& std_segs,
  297.  const CSeq_align& align)
  298. {
  299.     bool cont = true;
  300.     size_t num_stdseg = 0;
  301.     ITERATE( TStd, stdseg_iter, std_segs) {
  302.         ++num_stdseg;
  303.         const CStd_seg& stdseg = **stdseg_iter;
  304.         size_t dim = stdseg.GetDim();
  305.         // assert dim >= 2
  306.         if ( !x_ValidateDim(stdseg, align, num_stdseg) ) {
  307.             cont = false;
  308.             continue;
  309.         }
  310.         // assert dim == Loc.size()
  311.         if ( dim != stdseg.GetLoc().size() ) {
  312.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  313.                 "Mismatch between specified dimension (" +
  314.                 NStr::UIntToString(dim) + 
  315.                 ") and number of Seq-locs (" + 
  316.                 NStr::UIntToString(stdseg.GetLoc().size()) + ") in stdseg " +
  317.                 NStr::UIntToString(num_stdseg), align);
  318.             cont = false;
  319.             continue;
  320.         }
  321.         // assert dim == Ids.size()
  322.         if ( stdseg.IsSetIds() ) {
  323.             if ( dim != stdseg.GetIds().size() ) {
  324.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsDimMismatch,
  325.                     "Mismatch between specified dimension (" +
  326.                     NStr::UIntToString(dim) + 
  327.                     ") and number of Seq-ids (" + 
  328.                     NStr::UIntToString(stdseg.GetIds().size()) + ")",
  329.                     align);
  330.                 cont = false;
  331.                 continue;
  332.             }
  333.         }
  334.     }
  335.     if( cont ) {
  336.         x_ValidateStrand(std_segs, align);
  337.         x_ValidateFastaLike(std_segs, align);
  338.         x_ValidateSegmentGap(std_segs, align);
  339.         
  340.         if ( m_Imp.IsRemoteFetch() ) {
  341.             x_ValidateSeqId(align);
  342.             x_ValidateSeqLength(std_segs, align);
  343.         }
  344.     }
  345. }
  346. template <typename T>
  347. bool CValidError_align::x_ValidateDim
  348. (T& obj,
  349.  const CSeq_align& align,
  350.  size_t part)
  351. {
  352.     if ( !obj.IsSetDim() ) {
  353.         string msg = "Dim not set";
  354.         if ( part > 0 ) {
  355.             msg += " Part " + NStr::UIntToString(part);
  356.         }
  357.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsInvalidDim, msg, align);
  358.         return false;
  359.     }
  360.     size_t dim = obj.GetDim();        
  361.     if ( dim < 2 ) {
  362.         string msg = "Dimension (" + NStr::UIntToString(dim) + 
  363.             ") must be at least 2.";
  364.         if ( part > 0 ) {
  365.             msg += " Part " + NStr::UIntToString(part);
  366.         }
  367.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegsInvalidDim, msg, align);
  368.         return false;
  369.     }
  370.     return true;
  371. }
  372. //===========================================================================
  373. // x_ValidateStrand:
  374. //
  375. //  Check if the  strand is consistent in SeqAlignment of global
  376. //  or partial type.
  377. //===========================================================================
  378. void CValidError_align::x_ValidateStrand
  379. (const TDenseg& denseg,
  380.  const CSeq_align& align)
  381. {
  382.     if ( !denseg.IsSetStrands() ) {
  383.         return;
  384.     }
  385.     
  386.     size_t dim = denseg.GetDim();
  387.     size_t numseg = denseg.GetNumseg();
  388.     const CDense_seg::TStrands& strands = denseg.GetStrands();
  389.     // go through id for each alignment sequence
  390.     for ( size_t id = 0; id < dim; ++id ) {
  391.         ENa_strand strand1 = strands[id];
  392.         
  393.         for ( size_t seg = 0; seg < numseg; ++seg ) {
  394.             ENa_strand strand2 = strands[id + (seg * dim)];
  395.             // skip undefined strand
  396.             if ( strand2 == eNa_strand_unknown  ||
  397.                  strand2 == eNa_strand_other ) {
  398.                 continue;
  399.             }
  400.             if ( strand1 == eNa_strand_unknown  ||
  401.                  strand1 == eNa_strand_other ) {
  402.                 strand1 = strand2;
  403.                 continue;
  404.             }
  405.             // strands should be same for a given seq-id
  406.             if ( strand1 != strand2 ) {
  407.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_StrandRev,
  408.                     "The strand labels for SeqId " + 
  409.                     denseg.GetIds()[id]->AsFastaString() +
  410.                     " are inconsistent across the alignment. "
  411.                     "The first inconsistent region is the " + 
  412.                     NStr::UIntToString(seg), align);
  413.                     break;
  414.             }
  415.         }
  416.     }
  417. }
  418. void CValidError_align::x_ValidateStrand
  419. (const TPacked& packed,
  420.  const CSeq_align& align)
  421. {
  422.     if ( !packed.IsSetStrands() ) {
  423.         return;
  424.     }
  425.     size_t dim = packed.GetDim();
  426.     const CPacked_seg::TPresent& present = packed.GetPresent();
  427.     const CPacked_seg::TStrands& strands = packed.GetStrands();
  428.     CPacked_seg::TStrands::const_iterator strand = strands.begin();
  429.     
  430.     vector<ENa_strand> id_strands(dim, eNa_strand_unknown);
  431.     Uchar mask = 0x01;
  432.     size_t present_size = present.size();
  433.     for ( size_t i = 0; i < present_size; ++i ) {
  434.         if ( present[i] == 0 ) {   // no bits in this char
  435.             continue;
  436.         }
  437.         for ( int shift = 7; shift >= 0; --shift ) {
  438.             if ( present[i] & (mask << shift) ) {
  439.                 size_t id = i * 8 + 7 - shift;
  440.                 if ( *strand == eNa_strand_unknown  ||  
  441.                      *strand == eNa_strand_other ) {
  442.                     ++strand;
  443.                     continue;
  444.                 }
  445.                 
  446.                 if ( id_strands[id] == eNa_strand_unknown  || 
  447.                      id_strands[id] == eNa_strand_other ) {
  448.                     id_strands[id] = *strand;
  449.                     ++strand;
  450.                     continue;
  451.                 }
  452.                 
  453.                 if ( id_strands[id] != *strand ) {
  454.                     CPacked_seg::TIds::const_iterator id_iter =
  455.                         packed.GetIds().begin();
  456.                     for ( ; id; --id ) {
  457.                         ++id_iter;
  458.                     }
  459.                     
  460.                     PostErr(eDiag_Error, eErr_SEQ_ALIGN_StrandRev,
  461.                         "Strand for SeqId " + (*id_iter)->AsFastaString() +
  462.                         " are inconsistent across the alignment", align);
  463.                 }
  464.                 ++strand;
  465.             }
  466.         }
  467.     }
  468. }
  469. void CValidError_align::x_ValidateStrand
  470. (const TStd& std_segs,
  471.  const CSeq_align& align)
  472. {
  473.     map< CConstRef<CSeq_id>, ENa_strand > strands;
  474.     ITERATE ( TStd, stdseg, std_segs ) {
  475.         ITERATE ( CStd_seg::TLoc, loc_iter, (*stdseg)->GetLoc() ) {
  476.             const CSeq_loc& loc = **loc_iter;
  477.             
  478.             if ( !IsOneBioseq(loc, m_Scope) ) {
  479.                 // !!! should probably be an error
  480.                 continue;
  481.             }
  482.             CConstRef<CSeq_id> id(&GetId(loc, m_Scope));
  483.             ENa_strand strand = GetStrand(loc, m_Scope);
  484.             if ( strand == eNa_strand_unknown  || 
  485.                  strand == eNa_strand_other ) {
  486.                 continue;
  487.             }
  488.             if ( strands[id] == eNa_strand_unknown  ||
  489.                  strands[id] == eNa_strand_other ) {
  490.                 strands[id] = strand;
  491.             }
  492.             if ( strands[id] != strand ) {
  493.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_StrandRev,
  494.                     "Strands for SeqId " + id->AsFastaString() + 
  495.                     " are inconsistent across the alignment", align);
  496.             }
  497.         }
  498.     }
  499. }
  500. //===========================================================================
  501. // x_ValidateFastaLike:
  502. //
  503. //  Check if an alignment is FASTA-like. 
  504. //  Alignment is FASTA-like if all gaps are at the end with dimensions > 2.
  505. //===========================================================================
  506. void CValidError_align::x_ValidateFastaLike
  507. (const TDenseg& denseg,
  508.  const CSeq_align& align)
  509. {
  510.     // check only global or partial type
  511.     if ( (align.GetType() != CSeq_align::eType_global  &&
  512.          align.GetType() != CSeq_align::eType_partial) ||
  513.          denseg.GetDim() <= 2 ) {
  514.         return;
  515.     }
  516.     size_t dim = denseg.GetDim();
  517.     size_t numseg = denseg.GetNumseg();
  518.     vector<string> fasta_like;
  519.     for ( size_t id = 0; id < dim; ++id ) {
  520.         bool gap = false;
  521.         
  522.         const CDense_seg::TStarts& starts = denseg.GetStarts();
  523.         for ( size_t seg = 0; seg < numseg; ++ seg ) {
  524.             // if start value is -1, set gap flag to true
  525.             if ( starts[id + (dim * seg)] < 0 ) {
  526.                 gap = true;
  527.             } else if ( gap  ) {
  528.                 // if a positive start value is found after the initial -1 
  529.                 // start value, it's not fasta like. 
  530.                 //no need to check this sequence further
  531.                 break;
  532.             } 
  533.             if ( seg == numseg - 1  &&  gap ) {
  534.                 // if no more positive start value are found after the initial
  535.                 // -1 start value, it's fasta like
  536.                 fasta_like.push_back(denseg.GetIds()[id]->AsFastaString());
  537.             }
  538.         }
  539.     }
  540.     if ( !fasta_like.empty() ) {
  541.         string fasta_like_ids;
  542.         bool first = true;
  543.         ITERATE( vector<string>, idstr, fasta_like ) {
  544.             if ( first ) {
  545.                 first = false;
  546.             } else {
  547.                 fasta_like_ids += ", ";
  548.             }
  549.             fasta_like_ids += *idstr;
  550.         }
  551.         fasta_like_ids += ".";
  552.         PostErr(eDiag_Error, eErr_SEQ_ALIGN_FastaLike,
  553.             "This may be a fasta-like alignment for SeqIds: " + 
  554.             fasta_like_ids, align);
  555.     }
  556. }           
  557. void CValidError_align::x_ValidateFastaLike
  558. (const TPacked& packed,
  559.  const CSeq_align& align)
  560. {
  561.     // check only global or partial type
  562.     if ( align.GetType() == CSeq_align::eType_global  ||
  563.          align.GetType() == CSeq_align::eType_partial ||
  564.          packed.GetDim() <= 2 ) {
  565.         return;
  566.     }
  567.     static Uchar bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  568.     
  569.     size_t dim = packed.GetDim();
  570.     size_t numseg = packed.GetNumseg();
  571.     CPacked_seg::TIds::const_iterator id_iter = packed.GetIds().begin();
  572.     const CPacked_seg::TPresent& present = packed.GetPresent();
  573.     for ( size_t id = 0; id < dim;  ++id, ++id_iter ) {
  574.         bool gap = false;
  575.         for ( size_t seg = 0; seg < numseg; ++ seg ) {
  576.             // if a segment is not present, set gap flag to true
  577.             size_t i = id + (dim * seg);
  578.             if ( !(present[i / 8] & bits[i % 8]) ) {
  579.                 gap = true;
  580.             } else if ( gap ) {
  581.                 // if a segment is found later, then it's not fasta like, 
  582.                 // no need to check this sequence further.
  583.                 break;
  584.             } 
  585.             if ( seg == numseg - 1  &&  gap ) {
  586.                 // if no more segments are found for this sequence, 
  587.                 // then it's  fasta like.
  588.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_FastaLike,
  589.                     "This may be a fasta-like alignment for SeqId: " + 
  590.                     (*id_iter)->AsFastaString(), align);
  591.             }
  592.         }
  593.     }
  594. }
  595. void CValidError_align::x_ValidateFastaLike
  596. (const TStd& std_segs,
  597.  const CSeq_align& align)
  598. {
  599.     // check only global or partial type
  600.     if ( align.GetType() == CSeq_align::eType_global  ||
  601.          align.GetType() == CSeq_align::eType_partial ) {
  602.         return;
  603.     }
  604.     // suspected seq-ids
  605.     typedef map< CConstRef<CSeq_id>, bool > TIdGapMap;
  606.     TIdGapMap fasta_like;
  607.     ITERATE ( TStd, stdseg, std_segs ) {
  608.         ITERATE ( CStd_seg::TLoc, loc_iter, (*stdseg)->GetLoc() ) {
  609.             const CSeq_loc& loc = **loc_iter;
  610.             
  611.             if ( !IsOneBioseq(loc, m_Scope) ) {
  612.                 // !!! should probably be an error
  613.                 continue;
  614.             }
  615.             CConstRef<CSeq_id> id(&GetId(loc, m_Scope));
  616.             bool gap = loc.IsEmpty()  ||  loc.IsNull();
  617.             if ( gap  &&  fasta_like.find(id) == fasta_like.end() ) {
  618.                 fasta_like[id] = true;
  619.             }
  620.             if ( !gap  &&  fasta_like.find(id) != fasta_like.end() ) {
  621.                 fasta_like[id] = false;
  622.             }
  623.         }
  624.     }
  625.     
  626.     ITERATE ( TIdGapMap, iter, fasta_like ) {
  627.         if ( iter->second ) {
  628.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_FastaLike,
  629.                 "This may be a fasta-like alignment for SeqId: " + 
  630.                 iter->first->AsFastaString(), align);
  631.         }
  632.     }
  633. }
  634. //===========================================================================
  635. // x_ValidateSegmentGap:
  636. //
  637. // Check if there is a gap for all sequences in a segment.
  638. //===========================================================================
  639. void CValidError_align::x_ValidateSegmentGap
  640. (const TDenseg& denseg,
  641.  const CSeq_align& align)
  642. {
  643.     int numseg  = denseg.GetNumseg();
  644.     int dim     = denseg.GetDim();
  645.     const CDense_seg::TStarts& starts = denseg.GetStarts();
  646.     for ( int seg = 0; seg < numseg; ++seg ) {
  647.         bool seggap = true;
  648.         for ( int id = 0; id < dim; ++id ) {
  649.             if ( starts[seg * dim + id] != -1 ) {
  650.                 seggap = false;
  651.                 break;
  652.             }
  653.         }
  654.         if ( seggap ) {
  655.             // no sequence is present in this segment
  656.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegmentGap,
  657.                 "Segment " + NStr::UIntToString(seg) + " contains only gaps.",
  658.                 align);
  659.         }
  660.     }
  661. }
  662. void CValidError_align::x_ValidateSegmentGap
  663. (const TPacked& packed,
  664.  const CSeq_align& align)
  665. {
  666.     static Uchar bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  667.     size_t numseg = packed.GetNumseg();
  668.     size_t dim = packed.GetDim();
  669.     const CPacked_seg::TPresent& present = packed.GetPresent();
  670.     for ( size_t seg = 0; seg < numseg;  ++seg) {
  671.         size_t id = 0;
  672.         for ( ; id < dim; ++id ) {
  673.             size_t i = id + (dim * seg);
  674.             if ( (present[i / 8] & bits[i % 8]) ) {
  675.                 break;
  676.             }
  677.         }
  678.         if ( id == dim ) {
  679.             // no sequence is present in this segment
  680.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegmentGap,
  681.                 "Segment " + NStr::UIntToString(seg) + "contains only gaps.",
  682.                 align);
  683.         }
  684.     }       
  685. }
  686. void CValidError_align::x_ValidateSegmentGap
  687. (const TStd& std_segs,
  688.  const CSeq_align& align)
  689. {
  690.     size_t seg = 0;
  691.     ITERATE ( TStd, stdseg, std_segs ) {
  692.         bool gap = true;
  693.         ITERATE ( CStd_seg::TLoc, loc, (*stdseg)->GetLoc() ) {
  694.             if ( !(*loc)->IsEmpty()  ||  !(*loc)->IsEmpty() ) {
  695.                 gap = false;
  696.                 break;
  697.             }
  698.         }
  699.         if ( gap ) {
  700.             // no sequence is present in this segment
  701.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SegmentGap,
  702.                 "Segment " + NStr::UIntToString(seg) + "contains only gaps.",
  703.                 align);
  704.         }
  705.         ++seg;
  706.     }
  707. }
  708. //===========================================================================
  709. // x_ValidateSeqIdInSeqAlign:
  710. //
  711. //  Validate SeqId in sequence alignment.
  712. //===========================================================================
  713. void CValidError_align::x_ValidateSeqId(const CSeq_align& align)
  714. {
  715.     vector< CRef< CSeq_id > > ids;
  716.     x_GetIds(align, ids);
  717.     ITERATE( vector< CRef< CSeq_id > >, id_iter, ids ) {
  718.         const CSeq_id& id = **id_iter;
  719.         if ( id.IsLocal() ) {
  720.             if ( !m_Scope->GetBioseqHandle(id) ) {
  721.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_SeqIdProblem,
  722.                     "The sequence corresponding to SeqId " + 
  723.                     id.AsFastaString() + " could not be found.",
  724.                     align);
  725.             }
  726.         }
  727.     }
  728. }
  729. void CValidError_align::x_GetIds
  730. (const CSeq_align& align,
  731.  vector< CRef< CSeq_id > >& ids)
  732. {
  733.     ids.clear();
  734.     switch ( align.GetSegs().Which() ) {
  735.     case CSeq_align::C_Segs::e_Dendiag:
  736.         ITERATE( TDendiag, diag_seg, align.GetSegs().GetDendiag() ) {
  737.             const vector< CRef< CSeq_id > >& diag_ids = (*diag_seg)->GetIds();
  738.             copy(diag_ids.begin(), diag_ids.end(), back_inserter(ids));
  739.         }
  740.         break;
  741.         
  742.     case CSeq_align::C_Segs::e_Denseg:
  743.         ids = align.GetSegs().GetDenseg().GetIds();
  744.         break;
  745.         
  746.     case CSeq_align::C_Segs::e_Packed:
  747.         copy(align.GetSegs().GetPacked().GetIds().begin(),
  748.              align.GetSegs().GetPacked().GetIds().end(),
  749.              back_inserter(ids));
  750.         break;
  751.         
  752.     case CSeq_align::C_Segs::e_Std:
  753.         ITERATE( TStd, std_seg, align.GetSegs().GetStd() ) {
  754.             ITERATE( CStd_seg::TLoc, loc, (*std_seg)->GetLoc() ) {
  755.                 CSeq_id* idp = const_cast<CSeq_id*>(&GetId(**loc, m_Scope));
  756.                 CRef<CSeq_id> ref(idp);
  757.                 ids.push_back(ref);
  758.             }
  759.         }
  760.         break;
  761.             
  762.     default:
  763.         break;
  764.     }
  765. }
  766. //===========================================================================
  767. // x_ValidateSeqLength:
  768. //
  769. //  Check segment length, start and end point in Dense_diag, Dense_seg,  
  770. //  Packed_seg and Std_seg.
  771. //===========================================================================
  772. // Make sure that, in Dense_diag alignment, segment length is not greater
  773. // than Bioseq length
  774. void CValidError_align::x_ValidateSeqLength
  775. (const CDense_diag& dendiag,
  776.  size_t dendiag_num,
  777.  const CSeq_align& align)
  778. {
  779.     size_t dim = dendiag.GetDim();
  780.     TSeqPos len = dendiag.GetLen();
  781.     const CDense_diag::TIds& ids = dendiag.GetIds();
  782.     
  783.     CDense_diag::TStarts::const_iterator starts_iter = 
  784.             dendiag.GetStarts().begin();
  785.     
  786.     for ( size_t id = 0; id < dim; ++id ) {
  787.         TSeqPos bslen = GetLength(*(ids[id]), m_Scope);
  788.         TSeqPos start = *starts_iter;
  789.         // verify start
  790.         if ( start > bslen ) {
  791.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_StartMorethanBiolen,
  792.                     "Start (" + NStr::UIntToString(start) +
  793.                     ") exceeds bioseq length (" +
  794.                     NStr::UIntToString(bslen) +
  795.                     ") for seq-id " + ids[id]->AsFastaString() +
  796.                     "in dendiag " + NStr::UIntToString(dendiag_num),
  797.                     align);
  798.         }
  799.         
  800.         // verify length
  801.         if ( start + len > bslen ) {
  802.             PostErr(eDiag_Error, eErr_SEQ_ALIGN_SumLenStart,
  803.                     "Start + length (" + NStr::UIntToString(start + len) +
  804.                     ") exceeds bioseq length (" +
  805.                     NStr::UIntToString(bslen) +
  806.                     ") for seq-id " + ids[id]->AsFastaString() +
  807.                     "in dendiag " + NStr::UIntToString(dendiag_num),
  808.                     align);
  809.         }
  810.         ++starts_iter;
  811.     }
  812. }
  813.         
  814. void CValidError_align::x_ValidateSeqLength
  815. (const TDenseg& denseg,
  816.  const CSeq_align& align)
  817. {
  818.     int dim     = denseg.GetDim();
  819.     int numseg  = denseg.GetNumseg();
  820.     const CDense_seg::TIds& ids       = denseg.GetIds();
  821.     const CDense_seg::TStarts& starts = denseg.GetStarts();
  822.     const CDense_seg::TLens& lens      = denseg.GetLens();
  823.     bool minus = false;
  824.     for ( int id = 0; id < dim; ++id ) {
  825.         TSeqPos bslen = GetLength(*(ids[id]), m_Scope);
  826.         minus = denseg.IsSetStrands()  &&
  827.             denseg.GetStrands()[id] == eNa_strand_minus;
  828.         
  829.         for ( int seg = 0; seg < numseg; ++seg ) {
  830.             size_t curr_index = 
  831.                 id + (minus ? numseg - seg - 1 : seg) * dim;
  832.             // no need to verify if segment is not present
  833.             if ( starts[curr_index] == -1 ) {
  834.                 continue;
  835.             }
  836.             size_t lens_index = minus ? numseg - seg - 1 : seg;
  837.             // verify that start plus segment does not exceed total bioseq len
  838.             if ( starts[curr_index] + lens[lens_index] > bslen ) {
  839.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_SumLenStart,
  840.                     "Start + segment length (" + 
  841.                     NStr::UIntToString(starts[curr_index] + lens[lens_index]) +
  842.                     ") exceeds bioseq length (" +
  843.                     NStr::UIntToString(bslen) + ")", align);
  844.             }
  845.             // find the next segment that is present
  846.             size_t next_index = curr_index;
  847.             int next_seg;
  848.             for ( next_seg = seg + 1; next_seg < numseg; ++next_seg ) {
  849.                 next_index = 
  850.                     id + (minus ? numseg - next_seg - 1 : next_seg) * dim;
  851.                 
  852.                 if ( starts[next_index] != -1 ) {
  853.                     break;
  854.                 }
  855.             }
  856.             if ( next_seg == numseg  ||  next_index == curr_index ) {
  857.                 continue;
  858.             }
  859.             // length plus start should be equal to the closest next 
  860.             // start that is not -1
  861.             if ( starts[curr_index] + (TSignedSeqPos)lens[lens_index] !=
  862.                 starts[next_index] ) {
  863.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_DensegLenStart,
  864.                     "Start + segment length (" + 
  865.                     NStr::UIntToString(starts[curr_index] + lens[lens_index]) +
  866.                     ") exceeds next start (" +
  867.                     NStr::UIntToString(starts[next_index]) + ")", align);
  868.             }
  869.         }
  870.     }
  871. }
  872. void CValidError_align::x_ValidateSeqLength
  873. (const TPacked& packed,
  874.  const CSeq_align& align)
  875. {
  876.     static Uchar bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  877.     size_t dim = packed.GetDim();
  878.     size_t numseg = packed.GetNumseg();
  879.     //CPacked_seg::TStarts::const_iterator start =
  880.     //    packed.GetStarts().begin();
  881.     const CPacked_seg::TPresent& present = packed.GetPresent();
  882.     for ( size_t id = 0; id < dim; ++id ) {
  883.         for ( size_t seg = 0; seg < numseg; ++seg ) {
  884.             size_t i = id + seg * dim;
  885.             if ( (present[i / 8] & bits[i % 8]) ) {
  886.                 // !!!
  887.             }
  888.         }
  889.     }
  890. }
  891. void CValidError_align::x_ValidateSeqLength
  892. (const TStd& std_segs,
  893.  const CSeq_align& align)
  894. {
  895.     ITERATE( TStd, iter, std_segs ) {
  896.         const CStd_seg& stdseg = **iter;
  897.         ITERATE ( CStd_seg::TLoc, loc_iter, stdseg.GetLoc() ) {
  898.             const CSeq_loc& loc = **loc_iter;
  899.     
  900.             if ( loc.IsWhole()  || loc.IsEmpty()  ||  loc.IsNull() ) {
  901.                 continue;
  902.             }
  903.             if ( !IsOneBioseq(loc, m_Scope) ) {
  904.                 continue;
  905.             }
  906.             TSeqPos from = loc.GetTotalRange().GetFrom();
  907.             TSeqPos to   = loc.GetTotalRange().GetTo();
  908.             TSeqPos loclen = GetLength( loc, m_Scope);
  909.             TSeqPos bslen = GetLength(GetId(loc, m_Scope), m_Scope);
  910.             string  bslen_str = NStr::UIntToString(bslen);
  911.             string label;
  912.             loc.GetLabel(&label);
  913.             if ( from > bslen - 1 ) { 
  914.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_StartMorethanBiolen,
  915.                     "Loaction: " + label + ". From (" + 
  916.                     NStr::UIntToString(from) + 
  917.                     ") is more than bioseq length (" + bslen_str + ")", 
  918.                     align);
  919.             }
  920.             if ( to > bslen - 1 ) { 
  921.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_EndMorethanBiolen,
  922.                     "Loaction: " + label + ". To (" + NStr::UIntToString(to) +
  923.                     ") is more than bioseq length (" + bslen_str + ")", align);
  924.             }
  925.             if ( loclen > bslen ) {
  926.                 PostErr(eDiag_Error, eErr_SEQ_ALIGN_LenMorethanBiolen,
  927.                     "Loaction: " + label + ". Length (" + 
  928.                     NStr::UIntToString(loclen) + 
  929.                     ") is more than bioseq length (" + bslen_str + ")", align);
  930.             }
  931.         }
  932.     }
  933. }
  934. END_SCOPE(validator)
  935. END_SCOPE(objects)
  936. END_NCBI_SCOPE
  937. /*
  938. * ===========================================================================
  939. *
  940. * $Log: validerror_align.cpp,v $
  941. * Revision 1000.1  2004/06/01 19:47:45  gouriano
  942. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  943. *
  944. * Revision 1.8  2004/05/21 21:42:56  gorelenk
  945. * Added PCH ncbi_pch.hpp
  946. *
  947. * Revision 1.7  2003/09/30 18:30:38  shomrat
  948. * changed unsigned to signed to eliminate infinite loop
  949. *
  950. * Revision 1.6  2003/06/02 16:06:43  dicuccio
  951. * Rearranged src/objects/ subtree.  This includes the following shifts:
  952. *     - src/objects/asn2asn --> arc/app/asn2asn
  953. *     - src/objects/testmedline --> src/objects/ncbimime/test
  954. *     - src/objects/objmgr --> src/objmgr
  955. *     - src/objects/util --> src/objmgr/util
  956. *     - src/objects/alnmgr --> src/objtools/alnmgr
  957. *     - src/objects/flat --> src/objtools/flat
  958. *     - src/objects/validator --> src/objtools/validator
  959. *     - src/objects/cddalignview --> src/objtools/cddalignview
  960. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  961. * replaces the three libmmdb? libs.
  962. *
  963. * Revision 1.5  2003/05/28 16:24:40  shomrat
  964. * Report a single FastaLike error from each alignment
  965. *
  966. * Revision 1.4  2003/04/29 14:58:07  shomrat
  967. * Implemented SeqAlign validation
  968. *
  969. * Revision 1.3  2003/03/31 14:40:52  shomrat
  970. * $id: -> $id$
  971. *
  972. * Revision 1.2  2002/12/24 16:52:42  shomrat
  973. * Changes to include directives
  974. *
  975. * Revision 1.1  2002/12/23 20:15:59  shomrat
  976. * Initial submission after splitting former implementation
  977. *
  978. *
  979. * ===========================================================================
  980. */