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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: cav_function.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:41:19  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: cav_function.cpp,v 1000.2 2004/06/01 19:41:19 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:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      C interfaced function body for cddalignview as function call
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistl.hpp>
  43. #include <corelib/ncbistre.hpp>
  44. #include <corelib/ncbi_limits.h>
  45. #include <corelib/ncbidiag.hpp>
  46. #include <list>
  47. #include <memory>
  48. #include <objects/cdd/Cdd.hpp>
  49. #include <objects/ncbimime/Ncbi_mime_asn1.hpp>
  50. #include <objects/ncbimime/Biostruc_seqs.hpp>
  51. #include <objects/ncbimime/Biostruc_align.hpp>
  52. #include <objects/ncbimime/Biostruc_align_seq.hpp>
  53. #include <objtools/cddalignview/cddalignview.h>
  54. #include <objtools/cddalignview/cav_seqset.hpp>
  55. #include <objtools/cddalignview/cav_alignset.hpp>
  56. #include <objtools/cddalignview/cav_asnio.hpp>
  57. #include <objtools/cddalignview/cav_alndisplay.hpp>
  58. BEGIN_NCBI_SCOPE
  59. USING_SCOPE(objects);
  60. static EDiagSev defaultDiagPostLevel;
  61. static int LoadASNFromIstream(CNcbiIstream& asnIstream,
  62.     const SeqEntryList* *sequences, const SeqAnnotList* *alignments)
  63. {
  64. *sequences = NULL;
  65. *alignments = NULL;
  66.     // try to decide what ASN type this is, and if it's binary or ascii
  67.     static const string
  68.         asciiMimeFirstWord = "Ncbi-mime-asn1",
  69.         asciiCDDFirstWord = "Cdd";
  70.     bool isMime = false, isCDD = false, isBinary = true;
  71.     string firstWord;
  72.     asnIstream >> firstWord;
  73.     if (firstWord == asciiMimeFirstWord) {
  74.         isMime = true;
  75.         isBinary = false;
  76.     } else if (firstWord == asciiCDDFirstWord) {
  77.         isCDD = true;
  78.         isBinary = false;
  79.     }
  80.     // try to read the file as various ASN types (if it's not clear from the first ascii word).
  81.     auto_ptr<SeqEntryList> newSequences(new SeqEntryList());
  82.     auto_ptr<SeqAnnotList> newAlignments(new SeqAnnotList());
  83.     bool readOK = false;
  84.     string err;
  85.     if (!isCDD) {
  86.         ERR_POST(Info << "trying to read input as " <<
  87.             ((isBinary) ? "binary" : "ascii") << " mime");
  88.         CNcbi_mime_asn1 mime;
  89.         SetDiagPostLevel(eDiag_Fatal); // ignore all but Fatal errors while reading data
  90.         asnIstream.seekg(0);
  91.         readOK = ReadASNFromIstream(asnIstream, mime, isBinary, err);
  92.         SetDiagPostLevel(defaultDiagPostLevel);
  93.         if (readOK) {
  94.             // copy lists
  95.             if (mime.IsStrucseqs()) {
  96.                 *newSequences = mime.GetStrucseqs().GetSequences();
  97.                 *newAlignments = mime.GetStrucseqs().GetSeqalign();
  98.             } else if (mime.IsAlignstruc()) {
  99.                 *newSequences = mime.GetAlignstruc().GetSequences();
  100.                 *newAlignments = mime.GetAlignstruc().GetSeqalign();
  101.             } else if (mime.IsAlignseq()) {
  102.                 *newSequences = mime.GetAlignseq().GetSequences();
  103.                 *newAlignments = mime.GetAlignseq().GetSeqalign();
  104.             }
  105.         } else {
  106.             ERR_POST(Warning << "error: " << err);
  107.         }
  108.     }
  109.     if (!readOK) {
  110.         ERR_POST(Info << "trying to read input as " <<
  111.             ((isBinary) ? "binary" : "ascii") << " cdd");
  112.         CCdd cdd;
  113.         SetDiagPostLevel(eDiag_Fatal); // ignore all but Fatal errors while reading data
  114.         asnIstream.seekg(0);
  115.         readOK = ReadASNFromIstream(asnIstream, cdd, isBinary, err);
  116.         SetDiagPostLevel(defaultDiagPostLevel);
  117.         if (readOK) {
  118.             newSequences->resize(1);
  119.             newSequences->front().Reset(&(cdd.SetSequences()));
  120.             *newAlignments = cdd.GetSeqannot();   // copy the list
  121.         } else {
  122.             ERR_POST(Warning << "error: " << err);
  123.         }
  124.     }
  125.     if (!readOK) {
  126.         ERR_POST(Error << "Input is not a recognized data type (Ncbi-mime-asn1 or Cdd)");
  127.         return CAV_ERROR_BAD_ASN;
  128.     }
  129.     *sequences = newSequences.release();
  130. *alignments = newAlignments.release();
  131.     return CAV_SUCCESS;
  132. }
  133. // checks two things for each slave sequence: that all the residues of the sequence
  134. // are present in the display, and that the aligned residues are in the right place
  135. // wrt the master
  136. static bool VerifyAlignmentData(const AlignmentSet *alignmentSet, const AlignmentDisplay *display)
  137. {
  138.     int alnLoc, masterLoc, slaveLoc, currentMasterLoc, currentSlaveLoc;
  139.     char masterChar, slaveChar;
  140.     const MasterSlaveAlignment *alignment;
  141.     for (int i=0; i<alignmentSet->alignments.size(); ++i) {
  142.         masterLoc = slaveLoc = -1;
  143.         alignment = alignmentSet->alignments[i];
  144.         for (alnLoc=0; alnLoc<display->GetWidth(); ++alnLoc) {
  145.             // get and check characters
  146.             masterChar = display->GetCharAt(alnLoc, 0);
  147.             if (masterChar == '?') {
  148.                 ERR_POST(Error << "bad alignment coordinate: loc " << alnLoc << " row " << 0);
  149.                 return false;
  150.             }
  151.             slaveChar = display->GetCharAt(alnLoc, 1 + i);
  152.             if (slaveChar == '?') {
  153.                 ERR_POST(Error << "bad alignment coordinate: loc " << alnLoc << " row " << (1+i));
  154.                 return false;
  155.             }
  156.             // advance seqLocs, check sequence string length and composition
  157.             if (!IsGap(masterChar)) {
  158.                 ++masterLoc;
  159.                 if (i == 0) {   // only need to check master once
  160.                     if (masterLoc >= alignment->master->sequenceString.size()) {
  161.                         ERR_POST(Error << "master sequence too long at alnLoc " << alnLoc
  162.                             << " row " << (i+1) << "masterLoc" << masterLoc);
  163.                         return false;
  164.                     } else if (toupper(masterChar) != toupper(alignment->master->sequenceString[masterLoc])) {
  165.                         ERR_POST(Error << "master sequence mismatch at alnLoc " << alnLoc
  166.                             << " row " << (i+1) << "masterLoc" << masterLoc);
  167.                         return false;
  168.                     }
  169.                 }
  170.             }
  171.             if (!IsGap(slaveChar)) {
  172.                 ++slaveLoc;
  173.                 if (slaveLoc >= alignment->slave->sequenceString.size()) {
  174.                     ERR_POST(Error << "slave sequence too long at alnLoc " << alnLoc
  175.                         << " row " << (i+1) << "slaveLoc" << slaveLoc);
  176.                     return false;
  177.                 } else if (toupper(slaveChar) != toupper(alignment->slave->sequenceString[slaveLoc])) {
  178.                     ERR_POST(Error << "slave sequence mismatch at alnLoc " << alnLoc
  179.                         << " row " << (i+1) << "slaveLoc" << slaveLoc);
  180.                     return false;
  181.                 }
  182.             }
  183.             currentMasterLoc = IsGap(masterChar) ? -1 : masterLoc;
  184.             currentSlaveLoc = IsGap(slaveChar) ? -1 : slaveLoc;
  185.             // check display characters, to see if they match alignment data
  186.             if (IsGap(slaveChar) || IsUnaligned(slaveChar)) {
  187.                 if (currentMasterLoc >= 0 && alignment->masterToSlave[currentMasterLoc] != -1) {
  188.                     ERR_POST(Error << "slave should be marked aligned at alnLoc " << alnLoc
  189.                         << " row " << (i+1));
  190.                     return false;
  191.                 }
  192.             }
  193.             if (IsAligned(slaveChar)) {
  194.                 if (!IsAligned(masterChar)) {
  195.                     ERR_POST(Error <<" slave marked aligned but master unaligned at alnLoc " << alnLoc
  196.                         << " row " << (i+1));
  197.                     return false;
  198.                 }
  199.                 if (alignment->masterToSlave[currentMasterLoc] == -1) {
  200.                     ERR_POST(Error << "slave incorrectly marked aligned at alnLoc " << alnLoc
  201.                         << " row " << (i+1));
  202.                     return false;
  203.                 }
  204.                 if (alignment->masterToSlave[currentMasterLoc] != currentSlaveLoc) {
  205.                     ERR_POST(Error << "wrong slave residue aligned at alnLoc " << alnLoc
  206.                         << " row " << (i+1));
  207.                     return false;
  208.                 }
  209.             }
  210.             // converse: make sure alignment data is correctly reflected in display
  211.             if (!IsGap(masterChar)) {
  212.                 if (alignment->masterToSlave[currentMasterLoc] == -1) {
  213.                     if (IsAligned(slaveChar)) {
  214.                         ERR_POST(Error << "slave should be unaligned at alnLoc " << alnLoc
  215.                             << " row " << (i+1));
  216.                         return false;
  217.                     }
  218.                 } else {    // aligned master
  219.                     if (!IsAligned(slaveChar)) {
  220.                         ERR_POST(Error << "slave should be aligned at alnLoc " << alnLoc
  221.                             << " row " << (i+1));
  222.                         return false;
  223.                     }
  224.                     if (currentSlaveLoc != alignment->masterToSlave[currentMasterLoc]) {
  225.                         ERR_POST(Error << "wrong slave residue aligned to master at alnLoc " << alnLoc
  226.                             << " row " << (i+1));
  227.                         return false;
  228.                     }
  229.                 }
  230.             }
  231.         }
  232.         // check seequence lengths
  233.         if (masterLoc != alignment->master->sequenceString.size() - 1 ||
  234.             slaveLoc != alignment->slave->sequenceString.size() - 1) {
  235.             ERR_POST(Error << "bad sequence lengths at row " << (i+1));
  236.             return false;
  237.         }
  238.     }
  239.     return true;
  240. }
  241. END_NCBI_SCOPE
  242. // leave the main function outside the NCBI namespace, just in case that might
  243. // cause any problems when linking it to C code...
  244. USING_NCBI_SCOPE;
  245. int CAV_DisplayMultiple(
  246.     const void *asnDataBlock,
  247.     unsigned int options,
  248.     unsigned int paragraphWidth,
  249.     double conservationThreshhold,
  250.     const char *title,
  251.     int nFeatures,
  252.     const AlignmentFeature *features)
  253. {
  254.     return CAV_DisplayMultiple(asnDataBlock, options, paragraphWidth,
  255.         conservationThreshhold, title, nFeatures, features, NULL, NULL);
  256. }
  257. int CAV_DisplayMultiple(
  258.     const void *asnDataBlock,
  259.     unsigned int options,
  260.     unsigned int paragraphWidth,
  261.     double conservationThreshhold,
  262.     const char *title,
  263.     int nFeatures,
  264.     const AlignmentFeature *alnFeatures,
  265.     CNcbiOstream *outputStream,
  266.     CNcbiOstream *diagnosticStream)
  267. {
  268.     // make sure C++ output streams are sync'ed with C's stdio
  269.     IOS_BASE::sync_with_stdio(true);
  270.     // set up output streams (send all diagnostic messages to a different stream)
  271.     CNcbiOstream *outStream;
  272.     if (outputStream)
  273.         outStream = outputStream;
  274.     else
  275.         outStream = &NcbiCout;
  276.     if (diagnosticStream)
  277.         SetDiagStream(diagnosticStream);
  278.     else
  279.         SetDiagStream(&NcbiCerr);
  280.     if (options & CAV_DEBUG)
  281.         SetDiagPostLevel(defaultDiagPostLevel = eDiag_Info);   // show all messages
  282.     else
  283.         SetDiagPostLevel(defaultDiagPostLevel = eDiag_Error);  // show only errors
  284.     // check option consistency
  285.     if (options & CAV_CONDENSED && !(options & CAV_TEXT || options & CAV_HTML)) {
  286.         ERR_POST(Error << "Cannot do condensed display except with text/HTML output");
  287.         return CAV_ERROR_BAD_PARAMS;
  288.     }
  289.     if (options & CAV_FASTA_LOWERCASE && !(options & CAV_FASTA)) {
  290.         ERR_POST(Error << "Cannot do fasta_lc option except with FASTA output");
  291.         return CAV_ERROR_BAD_PARAMS;
  292.     }
  293.     if (options & CAV_HTML_HEADER && !(options & CAV_HTML)) {
  294.         ERR_POST(Error << "Cannot do HTML header without HTML output");
  295.         return CAV_ERROR_BAD_PARAMS;
  296.     }
  297.     // load input data into an input stream
  298.     if (!asnDataBlock) {
  299.         ERR_POST(Critical << "NULL asnDataBlock parameter");
  300.         return CAV_ERROR_BAD_ASN;
  301.     }
  302.     CNcbiIstrstream asnIstrstream(static_cast<const char*>(asnDataBlock), kMax_Int);
  303.     // load asn data block
  304.     const SeqEntryList *seqs;
  305.     const SeqAnnotList *alns;
  306.     int retval = LoadASNFromIstream(asnIstrstream, &seqs, &alns);
  307.     if (retval != CAV_SUCCESS) {
  308.         ERR_POST(Critical << "Couldn't get sequence and alignment ASN data");
  309.         return retval;
  310.     }
  311.     auto_ptr<const SeqEntryList> sequencesASN(seqs);
  312.     auto_ptr<const SeqAnnotList> alignmentsASN(alns);
  313.     // process asn data, then free it
  314.     auto_ptr<SequenceSet> sequenceSet(new SequenceSet(*(sequencesASN.get())));
  315.     if (!sequenceSet.get() || sequenceSet->Status() != CAV_SUCCESS) {
  316.         ERR_POST(Critical << "Error processing sequence data");
  317.         return sequenceSet->Status();
  318.     }
  319.     auto_ptr<AlignmentSet> alignmentSet(new AlignmentSet(sequenceSet.get(), *(alignmentsASN.get())));
  320.     if (!alignmentSet.get() || alignmentSet->Status() != CAV_SUCCESS) {
  321.         ERR_POST(Critical << "Error processing alignment data");
  322.         return alignmentSet->Status();
  323.     }
  324.     sequencesASN.reset();
  325.     alignmentsASN.reset();
  326.     // create the alignment display structure
  327.     auto_ptr<AlignmentDisplay> display(new AlignmentDisplay(sequenceSet.get(), alignmentSet.get()));
  328.     if (!display.get() || display->Status() != CAV_SUCCESS) {
  329.         ERR_POST(Critical << "Error creating alignment display");
  330.         return display->Status();
  331.     }
  332.     // do verification
  333.     if (options & CAV_DEBUG) {
  334.         if (!VerifyAlignmentData(alignmentSet.get(), display.get())) {
  335.             ERR_POST(Critical << "AlignmentDisplay failed verification");
  336.             return CAV_ERROR_DISPLAY;
  337.         } else {
  338.             ERR_POST(Info << "AlignmentDisplay passed verification");
  339.         }
  340.     }
  341.     // display alignment with given parameters
  342.     ERR_POST(Info << "writing output...");
  343.     int
  344.         from = (options & CAV_LEFTTAILS) ? 0 : display->GetFirstAlignedLoc(),
  345.         to = (options & CAV_RIGHTTAILS) ? display->GetWidth()-1 : display->GetLastAlignedLoc();
  346.     if (options & CAV_SHOW_IDENTITY) conservationThreshhold = AlignmentDisplay::SHOW_IDENTITY;
  347.     if (options & CAV_TEXT || options & CAV_HTML) {
  348.         if (options & CAV_CONDENSED)
  349.             retval = display->DumpCondensed(*outStream, options,
  350.                 from, to, paragraphWidth, conservationThreshhold, title, nFeatures, alnFeatures);
  351.         else
  352.             retval = display->DumpText(*outStream, options,
  353.                 from, to, paragraphWidth, conservationThreshhold, title, nFeatures, alnFeatures);
  354.     } else if (options & CAV_FASTA) {
  355.         retval = display->DumpFASTA(from, to, paragraphWidth,
  356.             ((options & CAV_FASTA_LOWERCASE) > 0), *outStream);
  357.     }
  358. //    if (outStream != &NcbiCout) delete outStream;
  359.     if (retval != CAV_SUCCESS) {
  360.         ERR_POST(Error << "Error dumping display to output");
  361.         return retval;
  362.     }
  363.     return CAV_SUCCESS;
  364. }
  365. /*
  366. * ---------------------------------------------------------------------------
  367. * $Log: cav_function.cpp,v $
  368. * Revision 1000.2  2004/06/01 19:41:19  gouriano
  369. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  370. *
  371. * Revision 1.4  2004/05/21 21:42:51  gorelenk
  372. * Added PCH ncbi_pch.hpp
  373. *
  374. * Revision 1.3  2004/03/15 18:51:27  thiessen
  375. * prefer prefix vs. postfix ++/-- operators
  376. *
  377. * Revision 1.2  2003/06/02 16:06:41  dicuccio
  378. * Rearranged src/objects/ subtree.  This includes the following shifts:
  379. *     - src/objects/asn2asn --> arc/app/asn2asn
  380. *     - src/objects/testmedline --> src/objects/ncbimime/test
  381. *     - src/objects/objmgr --> src/objmgr
  382. *     - src/objects/util --> src/objmgr/util
  383. *     - src/objects/alnmgr --> src/objtools/alnmgr
  384. *     - src/objects/flat --> src/objtools/flat
  385. *     - src/objects/validator --> src/objtools/validator
  386. *     - src/objects/cddalignview --> src/objtools/cddalignview
  387. * In addition, libseq now includes six of the objects/seq... libs, and libmmdb
  388. * replaces the three libmmdb? libs.
  389. *
  390. * Revision 1.1  2003/03/19 19:04:12  thiessen
  391. * move again
  392. *
  393. * Revision 1.2  2003/03/19 16:06:28  thiessen
  394. * add <memory>
  395. *
  396. * Revision 1.1  2003/03/19 05:33:43  thiessen
  397. * move to src/app/cddalignview
  398. *
  399. * Revision 1.11  2003/03/18 22:35:06  thiessen
  400. * add C++ version of function that takes streams for output
  401. *
  402. * Revision 1.10  2003/02/03 17:52:03  thiessen
  403. * move CVS Log to end of file
  404. *
  405. * Revision 1.9  2003/01/21 18:01:07  thiessen
  406. * add condensed alignment display
  407. *
  408. * Revision 1.8  2002/11/08 19:38:11  thiessen
  409. * add option for lowercase unaligned in FASTA
  410. *
  411. * Revision 1.7  2002/02/08 19:53:17  thiessen
  412. * add annotation to text/HTML displays
  413. *
  414. * Revision 1.6  2001/05/17 15:01:41  lavr
  415. * Typos corrected
  416. *
  417. * Revision 1.5  2001/03/02 01:19:24  thiessen
  418. * add FASTA output
  419. *
  420. * Revision 1.4  2001/02/15 19:23:44  thiessen
  421. * add identity coloring
  422. *
  423. * Revision 1.3  2001/02/14 16:06:10  thiessen
  424. * add block and conservation coloring to HTML display
  425. *
  426. * Revision 1.2  2001/01/29 23:55:10  thiessen
  427. * add AlignmentDisplay verification
  428. *
  429. * Revision 1.1  2001/01/29 18:13:34  thiessen
  430. * split into C-callable library + main
  431. *
  432. */